数论专题测试——幸运数字

 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
",++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
",++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
",++ca,i);fuckpps=0;break;}
53             if(ksm(10,t/i)==1){ans=t/i;}
54         }
55         if(fuckpps)printf("Case %d: %lld
",++ca,ans);
56     }
57     return 0;
58 }
View Code

题意:找到一个最小的只有数字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。

原文地址:https://www.cnblogs.com/OYzx/p/5778343.html