标签:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 using namespace std; 7 typedef long long int64; 8 int64 L; 9 int ca; 10 int64 phi(int64 x){ 11 int64 t=x; 12 for (int64 i=2;i*i<=x;i++){ 13 if (x%i==0){ 14 t=t/i*(i-1); 15 while (x%i==0) x/=i; 16 } 17 } 18 if (x>1) t=t/x*(x-1); 19 return t; 20 } 21 int64 hs(int64 x,int64 y){ 22 long double t1=(long double)x*y/L; 23 int64 t2=x*y; 24 int64 t3=(t2-(long long)t1*L)%L; 25 return t3; 26 } 27 int64 ksm(int64 x,int64 y){ 28 if (y==0) return 1; 29 if (y==1) return x%L; 30 int64 d=ksm(x,y/2); 31 if (y%2==1) return hs(hs(d,d),x); 32 else return hs(d,d); 33 } 34 int main(){ 35 ca=0; 36 while (1){ 37 scanf("%lld",&L); 38 if (L==0) break; 39 if (L%16==0){ 40 printf("Case %d: %d\n",++ca,0); 41 continue; 42 } 43 while (L%2==0) L/=2; 44 L*=9; 45 if (L%5==0){ 46 printf("Case %d: %d\n",++ca,0); 47 continue; 48 } 49 int64 t=phi(L),tt=sqrt(t),ans;bool fuckpps=1; 50 for (int i=1;i*i<=t;i++){ 51 if (t%i) continue; 52 if (ksm(10,i)==1){printf("Case %d: %lld\n",++ca,i);fuckpps=0;break;} 53 if(ksm(10,t/i)==1){ans=t/i;} 54 } 55 if(fuckpps)printf("Case %d: %lld\n",++ca,ans); 56 } 57 return 0; 58 }
题意:找到一个最小的只有数字8的十进制正整数为给定正整数L的倍数,输出其长度。
做法:很容易得到一个式子:(10^x-1)*8/9=0(mod L),(10^x-1)/9是奇数,若L是16的倍数,则无解。否则把L中的2消去,再把8中多余的2去掉,因为(2,L)=1。再同时乘9,把1移过去,变为10^x=1(mod 9L‘),若L’中有质因子5则无解,因为此时10^x不可能与1同余。10与模数互质,根据欧拉定理,可知10^phi(9L‘)=1(mod 9L‘),x一定是phi(9L’)的约数,10不一定是模数的原根。然后枚举约数,快速幂check即可,也可以用bsgs,只是常数大,会TLE。
标签:
原文地址:http://www.cnblogs.com/OYzx/p/5778343.html