[题解](同余)POJ_3696_The Luckiest Number

Posted superminivan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解](同余)POJ_3696_The Luckiest Number相关的知识,希望对你有一定的参考价值。

还是挺难的吧......勉强看懂调了半天

首先表达式可以写成 8(10^x -1)/9,题意为求一个最小的x使L | 8(10^x -1)/9

设d=gcd(L,8)

L | 8(10^x -1)/9

<=>9L | 8(10^x -1)

<=>9L/d | 10^x -1 (因为 9L/d 和 8/d 互质了 所以 9L/d 能整除(8/d)*(10^x-1)和 8/d 无关,所以可以去掉)

<=>10^x 同余 1(mod 9L/d)

引理:

若a,n互质,则满足10^x同余1(mod n)的最小正整数x0是phi(n)的约数

反证法:

假设满足a^x 同余 1(mod n)的最小正整数x0不能整除phi(n)

设phi(n)=q*x0+r(0<r<x0),因为a^x0 同余1(mod n),所以a^(q*x0)同余1(mod n)

根据欧拉定理a^phi(n)同余1(mod n),所以a^r同余1(mod n),与x0最小矛盾

无解的时候就是q与10不互质的时候,因为若q与10有公因子d:
1.若d=2,q=2*k,那么10^x=2^x*5^x=1%2k
   即2^x*5^x=1+2k*m,左边为偶数,右边为奇数,显然矛盾。
2.若d=5,q=5*k,那么10^x=2^x*5^x=1%5k
   即2^x*5^x=1+5k*m,左边是5的倍数,右边不是5的倍数,显然矛盾。

注意:乘的时候会爆longlong,手写乘法,要用根号的试除法求约数,不然会T

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
ll n,cnt;
ll x[100000];
ll gcd(ll a,ll b){
    return b?gcd(b,a%b):a;
}
ll eular(ll n){
    ll ans=n;
    for(ll i=2;i*i<=n;i++){
        if(n%i==0){
            ans=ans/i*(i-1);
            while(n%i==0)n/=i;
        }
    }
    if(n>1)ans=ans/n*(n-1);
    return ans;
}
ll mul(ll a,ll b,ll mod){
    ll ans=0;
    while(b){
        if(b&1)ans=(ans+a)%mod;
        a=(a<<1)%mod;
        b>>=1;
    }
    return ans;
}
ll qpow(ll a,ll b,ll mod){
    ll base=a,ans=1;
    while(b){
        if(b&1)ans=mul(ans,base,mod);
        base=mul(base,base,mod);
        b>>=1;
    }
    return ans%mod;
}

int main(){
    int t=0;
    while(1){
        int fl=0;cnt=0;
        scanf("%lld",&n);
        if(n==0)break;
        ll d=9*n/gcd(n,8);
        if(gcd(10,d)!=1){
            printf("Case %d: 0\n",++t);
        }
        else{
            ll phi=eular(d);
            for(ll i=1;i*i<=phi;i++){
                if(phi%i==0){
                    x[++cnt]=i;
                    if(i*i!=phi)x[++cnt]=phi/i;
                }
            }
            
            sort(x+1,x+cnt+1);
            for(int i=1;i<=cnt;i++)
            if(qpow(10,x[i],d)==1){
                printf("Case %d: %lld\n",++t,x[i]);
                break;
            }
        }
    }
}

 

以上是关于[题解](同余)POJ_3696_The Luckiest Number的主要内容,如果未能解决你的问题,请参考以下文章

poj_3696_The Luckiest number

POJ - 3696 同余

「POJ3696」The Luckiest number数论,欧拉函数

poj-3696 The Luckiest number

POJ3696 The Luckiest Number

[POJ3696]The Luckiest number