POJ 3696 The Luckiest number

    技术2022-05-20  44

    比较难的一道数论题了。。。在练习赛的时候碰到,和队友YY了很久,没想到把n个8怎么表示出来

    首先,由于特殊性(每个位上都是8),我们把m=888...8(n个8)表示成m=8*(10^0+10^1+...+10^n-1)=8*(10^n-1)/9(关键之一)

    设m=k*l

    则8*(10^n-1)/9=k*l <=> 8*(10^n-1)/9 = 0 (mod l)

                                    <=> 8*(10^n-1) = 0 (mod 9*l)

    <=> 10^n-1 = 0 (mod gcd(8,l)*9*l)

    <=> 10^n =1 (mod gcd(8,l)*9*l)

    设p=gcd(8,l)*9*l,则10^n =1 (mod p)  (1)

    有欧拉定理,当10和p互素时,存在n=PHI(p),使得上式成立,如果10和p不互素,即gcd(10,l)!=1,则无解(关键之二)

     

    然后,PHI(m)并不是最小的答案,而是它的因子中满足等式(1)的最小的因子 (关键之三)

     

    并且根据前人经验,在求10^n%p时,一般的快速求幂会产生溢出错误(p超出int32),要用更BT的

     

    代码:

    #include<iostream> #include<cstdio> #include<memory.h> #include<algorithm> using namespace std; __int64 f[10000],cnt[10000],factor[100000]; __int64 l,M,f_num,factor_num; __int64 gcd(__int64 a,__int64 b) { if(b==0) return a; else return gcd(b,a%b); } __int64 eular(__int64 m)//求解PHI(m) { __int64 i,res=1; for(i=2;i*i<=m;i++) { if(m%i==0) { res*=i-1; m/=i; while(m%i==0) { res*=i; m/=i; } } } if(m>1) res*=m-1; return res; } void spilt(__int64 x)//因式分解x { __int64 i,j=x; f_num=0; for(i=2;i*i<=j;i++) { if(j%i==0) { f[f_num]=i; while(j%i==0) { cnt[f_num]++; j/=i; } f_num++; } } if(j>1) { f[f_num]=j; cnt[f_num++]=1; } } __int64 mod(__int64 a,__int64 b,__int64 m)//计算a*b%m { __int64 ret=0; while(b) { if(b&1) { ret+=a; if(ret>=m) ret-=m; } a+=a; if(a>=m) a-=m; b>>=1; } return ret; } __int64 pow(__int64 a,__int64 b,__int64 m)//计算a^b%m { __int64 ret=1; while(b) { if(b&1) ret=mod(ret,a,M); a=mod(a,a,M); b>>=1; } return ret; } void dfs(__int64 val,__int64 d)//dfs求一个数的所有因子 { if(d==f_num) { factor[factor_num++]=val; return; } __int64 sum=1; for(int i=1;i<=cnt[d];i++) { sum*=f[d]; dfs(val*sum,d+1); } dfs(val,d+1); } int main() { int i,j,ca=0; __int64 PHI; while(scanf("%I64d",&l)!=EOF) { if(l==0) break; printf("Case %d: ",++ca); //cout<<l<<" "<<gcd(l,8)<<endl; M=9*l/gcd(l,8); //cout<<M<<endl; if(gcd(M,10)!=1) { printf("0/n"); continue; } PHI=eular(M); //cout<<PHI<<endl; memset(cnt,0,sizeof(cnt)); spilt(PHI); factor_num=0; dfs(1,0); sort(factor,factor+factor_num); for(i=0;i<factor_num;i++) { if(pow(10,factor[i],M)==1) { cout<<factor[i]<<endl; break; } } } return 0; } 


    最新回复(0)