1 /** 2 大意: 给定小数(p/q),求其循环节的大小和循环节开始的位置 3 解法: 若出现循环 ai*2^m= aj%p; 4 即 2^m %p =1 5 若2与p 互素,则可由欧拉函数的, 6 不互素,需将其转化为互素的情况,,也就出现了循环节开始位置的差异; 7 8 值得学习的地方: 9 1、 10 首先,先对该分数 n/m 化简。 11 temp = gcd(n,m); 12 // n = n / temp 13 // m = m / temp 14 // n = n mod m 15 // 接下来就是需要知道一个分数化成k进制小数的方法: 16 // for i = 0 to 需要的位数 17 // n = n * k; 18 // bit[i] = n / m; 19 // 20 21 2、 22 a ^ x % q = 1,对于其任意一个解x ,它的最小解x0 | x 。 23 在a 与 q 互质的条件下,ψ(q) 是它的一个解。 24 所以有x0 | ψ(q)这样一个条件,可以先求出q的欧拉函数值ψ(q),再在它的因子中找最小解。 25 注意中间过程int可能溢出。 26 27 **/ 28 29 #include <iostream> 30 #include <algorithm> 31 #include <math.h> 32 using namespace std; 33 long long fn[1000000]; 34 long long gcd(long long a,long long b){ 35 if(b==0) 36 return a; 37 return gcd(b,a%b); 38 } 39 40 long long pow(long long a,long long b,long long m){ 41 if(b==0) 42 return 1; 43 long long c =1; 44 a =a%m; 45 while(b){ 46 if(b&1) 47 c = (long long )c*a%m; 48 a =(long long )a*a%m; 49 b>>=1; 50 } 51 return c; 52 } 53 54 long long eular(long long n){ 55 long long m = (long long )sqrt(n+0.5); 56 long long ans = n; 57 for(long long i=2;i<=m;i++) if(n%i==0){ 58 ans = ans/i*(i-1); 59 while(n%i==0) 60 n/=i; 61 } 62 if(n>1) 63 ans = ans/n*(n-1); 64 return ans; 65 } 66 67 int main() 68 { 69 long long n,m; 70 char c; 71 72 long long cur =1; 73 while(cin>>n>>c>>m){ 74 int temp = gcd(n,m); // 注意:一上午自己就是因为这个图省劲没有先将gcd(n,m)存起来,,导致后边的m/gcd(n,m) 一直是n与m的最大公约数是1的情况,即m没有得化简。。。 75 n = n/temp; 76 m = m/temp; 77 n = n%m; 78 long long ans1,ans2; 79 long long t=0; 80 while(m%2==0){ 81 m = m/2; 82 t++; 83 } 84 ans1 = t+1; 85 86 long long res = eular(m); 87 if(res==1){ 88 ans2 = 1; 89 }else{ 90 long long cnt =0; 91 // cout<<res<<endl; 92 for(long long i=1;i*i<=res;i++)if(res%i==0){ 93 fn[cnt++] = i; 94 fn[cnt++] = res/i; 95 } 96 sort(fn,fn+cnt); 97 for(long long i=0;i<cnt;i++){ 98 if(pow(2,fn[i],m)==1){ 99 ans2 = fn[i]; 100 break; 101 } 102 } 103 } 104 cout<<"Case #"<<cur++<<": "<<ans1<<","<<ans2<<endl; 105 } 106 return 0; 107 }
原文:http://www.cnblogs.com/Bang-cansee/p/3724269.html