斐波那契数列寻找mod n 循环节 模板

该代码来自ACdreamer

  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <stdio.h>
  5 #include <math.h>
  6 
  7 using namespace std;
  8 typedef unsigned long long LL;
  9 
 10 const int M = 2;
 11 
 12 struct Matrix
 13 {
 14     LL m[M][M];
 15 };
 16 
 17 Matrix A;
 18 Matrix I = {1,0,0,1};
 19 
 20 Matrix multi(Matrix a,Matrix b,LL MOD)
 21 {
 22     Matrix c;
 23     for(int i=0; i<M; i++)
 24     {
 25         for(int j=0; j<M; j++)
 26         {
 27             c.m[i][j] = 0;
 28             for(int k=0; k<M; k++)
 29                 c.m[i][j] = (c.m[i][j]%MOD + (a.m[i][k]%MOD)*(b.m[k][j]%MOD)%MOD)%MOD;
 30             c.m[i][j] %= MOD;
 31         }
 32     }
 33     return c;
 34 }
 35 
 36 Matrix power(Matrix a,LL k,LL MOD)
 37 {
 38     Matrix ans = I,p = a;
 39     while(k)
 40     {
 41         if(k & 1)
 42         {
 43             ans = multi(ans,p,MOD);
 44             k--;
 45         }
 46         k >>= 1;
 47         p = multi(p,p,MOD);
 48     }
 49     return ans;
 50 }
 51 
 52 LL gcd(LL a,LL b)
 53 {
 54     return b? gcd(b,a%b):a;
 55 }
 56 
 57 const int N = 400005;
 58 const int NN = 5005;
 59 
 60 LL num[NN],pri[NN];
 61 LL fac[NN];
 62 int cnt,c;
 63 
 64 bool prime[N];
 65 int p[N];
 66 int k;
 67 
 68 void isprime()
 69 {
 70     k = 0;
 71     memset(prime,true,sizeof(prime));
 72     for(int i=2; i<N; i++)
 73     {
 74         if(prime[i])
 75         {
 76             p[k++] = i;
 77             for(int j=i+i; j<N; j+=i)
 78                 prime[j] = false;
 79         }
 80     }
 81 }
 82 
 83 LL quick_mod(LL a,LL b,LL m)
 84 {
 85     LL ans = 1;
 86     a %= m;
 87     while(b)
 88     {
 89         if(b & 1)
 90         {
 91             ans = ans * a % m;
 92             b--;
 93         }
 94         b >>= 1;
 95         a = a * a % m;
 96     }
 97     return ans;
 98 }
 99 
100 LL legendre(LL a,LL p)
101 {
102     if(quick_mod(a,(p-1)>>1,p)==1) return 1;
103     else                           return -1;
104 }
105 
106 void Solve(LL n,LL pri[],LL num[])
107 {
108     cnt = 0;
109     LL t = (LL)sqrt(1.0*n);
110     for(int i=0; p[i]<=t; i++)
111     {
112         if(n%p[i]==0)
113         {
114             int a = 0;
115             pri[cnt] = p[i];
116             while(n%p[i]==0)
117             {
118                 a++;
119                 n /= p[i];
120             }
121             num[cnt] = a;
122             cnt++;
123         }
124     }
125     if(n > 1)
126     {
127         pri[cnt] = n;
128         num[cnt] = 1;
129         cnt++;
130     }
131 }
132 
133 void Work(LL n)
134 {
135     c = 0;
136     LL t = (LL)sqrt(1.0*n);
137     for(int i=1; i<=t; i++)
138     {
139         if(n % i == 0)
140         {
141             if(i * i == n) fac[c++] = i;
142             else
143             {
144                 fac[c++] = i;
145                 fac[c++] = n / i;
146             }
147         }
148     }
149 }
150 
151 LL find_loop(LL n)
152 {
153     Solve(n,pri,num);
154     LL ans=1;
155     for(int i=0; i<cnt; i++)
156     {
157         LL record=1;
158         if(pri[i]==2)
159             record=3;
160         else if(pri[i]==3)
161             record=8;
162         else if(pri[i]==5)
163             record=20;
164         else
165         {
166             if(legendre(5,pri[i])==1)
167                 Work(pri[i]-1);
168             else
169                 Work(2*(pri[i]+1));
170             sort(fac,fac+c);
171             for(int k=0; k<c; k++)
172             {
173                 Matrix a = power(A,fac[k]-1,pri[i]);
174                 LL x = (a.m[0][0]%pri[i]+a.m[0][1]%pri[i])%pri[i];
175                 LL y = (a.m[1][0]%pri[i]+a.m[1][1]%pri[i])%pri[i];
176                 if(x==1 && y==0)
177                 {
178                     record = fac[k];
179                     break;
180                 }
181             }
182         }
183         for(int k=1; k<num[i]; k++)
184             record *= pri[i];
185         ans = ans/gcd(ans,record)*record;
186     }
187     return ans;
188 }
189 
190 void Init()
191 {
192     A.m[0][0] = 1;
193     A.m[0][1] = 1;
194     A.m[1][0] = 1;
195     A.m[1][1] = 0;
196 }
197 
198 int main()
199 {
200     LL n;
201     Init();
202     isprime();
203     while(cin>>n)
204         cout<<find_loop(n)<<endl;
205     return 0;
206 }

 

posted on 2016-10-05 14:27  disppr  阅读(765)  评论(0编辑  收藏  举报