题意:
Bob最喜欢的数字是8,他的幸运数字是能整除L的全8序列的最短长度。
请找到Bob的幸运数字,若无则输出0
例如:L=1,ans=1;L=2,ans=1;L=8,ans=1;L=11,ans=2.
分析:
注意到凡是那种1111111..... 2222222..... 33333.....
之类的序列都可用这个式子来表示:k*(10^n-1)/9
进而简化:8 * (10^n-1)/9=L * k (k是一个整数)
-->8 * (10^n-1)=9L *
-->d=gcd(8,L) 8*(10^n-1)/d=9k * L/d
-->令p=8/d q=9kL/d p*(10^n-1)=q
--->因为p,q互质, 10^n=1 mod q
由欧拉定理可知,当q与10互质的时候,10^(phi(q))=1 mod q
所以无解的时候就是q与10不互质的时候,此外我们求phi(q)的所有因子,按小到大排序,第一个满足10^x =1 mod q的输出。
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #define LL long long using namespace std; const LL MAX=100000000000; LL phi(LL n){ LL x=n,i; LL ans=n; for(i=2;i*i<=x;i++){ if(x%i==0){ ans=ans/i*(i-1); while(x%i==0) x/=i; } } if(x!=1) ans=ans/x*(x-1); return ans; } LL multi(LL a,LL b,LL m){//a*b%m LL ret=0; while(b>0){ if(b&1){ ret+=a; if(ret>=m) ret-=m; } a+=a; if(a>=m) a-=m; b>>=1; } return ret; } LL quickmod(LL a,LL n,LL MOD){//a^n%MOD LL ans=1; ans%=MOD; for(;n>0;n>>=1,a=multi(a,a,MOD)) if(n&1) ans=multi(ans,a,MOD); return ans; } int main(){ int cas=0; LL n,i; while(~scanf("%lld",&n)&&n){ int k=0; while(n%2==0){ n/=2; k++; } if(k>3||n%5==0){ printf("Case %d: 0\n",++cas); continue; } n*=9; LL len=phi(n); LL ans=MAX; for(i=1;i*i<=len;i++){ if(len%i==0){ LL f=len/i; if(quickmod(10,i,n)==1) ans=min(ans,i); if(quickmod(10,f,n)==1) ans=min(ans,f); } } if(ans==MAX) ans=0; printf("Case %d: %lld\n",++cas,ans); } return 0; }