hdu 3978 Evil teacher's Final Problem (斐波那契数列的循环节)
题意:now he let you calculate G(n,k) .Here G(n,0) = f(n) , G(n,i) = f( G(n,i-1) ) (k >= i >= 1).其中f是斐波那契数列。
思路:其实就是hdu 4291的加强版:hdu 4291 解题报告
开一个1E4的数组存一下每一层的循环节就好了。
http://vjudge.net/contest/139429#overview 告一段落,完结撒花!
1/* ***********************************************
2Author :111qqz
3Created Time :Tue 01 Nov 2016 08:31:22 PM CST
4File Name :code/hdu/3978.cpp
5************************************************ */
6#include <cstdio>
7#include <cstring>
8#include <iostream>
9#include <algorithm>
10#include <vector>
11#include <queue>
12#include <set>
13#include <map>
14#include <string>
15#include <cmath>
16#include <cstdlib>
17#include <ctime>
18#define fst first
19#define sec second
20#define lson l,m,rt<<1
21#define rson m+1,r,rt<<1|1
22#define ms(a,x) memset(a,x,sizeof(a))
23typedef long long LL;
24#define pi pair < int ,int >
25#define MP make_pair
26using namespace std;
27const double eps = 1E-8;
28const int dx4[4]={1,0,0,-1};
29const int dy4[4]={0,-1,1,0};
30const int inf = 0x3f3f3f3f;
31struct Mat
32{
33 LL mat[2][2];
34 void clear()
35 {
36 ms(mat,0);
37 }
38}M,M1;
39Mat mul (Mat a,Mat b,LL mod)
40{
41 Mat c;
42 c.clear();
43 for ( int i = 0 ; i < 2 ; i++)
44 for ( int j = 0 ; j < 2 ; j++)
45 for ( int k = 0 ; k < 2 ; k++)
46 c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]%mod)%mod;
47 return c;
48}
49Mat mat_ksm(Mat a,LL b,LL mod)
50{
51 Mat res;
52 res.clear();
53 for ( int i = 0 ; i < 2 ; i++) res.mat[i][i] = 1;
54 while (b>0)
55 {
56 if (b&1) res = mul(res,a,mod);
57 b = b >> 1LL;
58 a = mul(a,a,mod);
59 }
60 return res;
61}
62LL gcd(LL a,LL b)
63{
64 return b?gcd(b,a%b):a;
65}
66const int N = 1E6+7;
67bool prime[N];
68int p[N];
69void isprime() //一个普通的筛
70{
71 int cnt = 0 ;
72 ms(prime,true);
73 for ( int i = 2 ; i < N ; i++)
74 {
75 if (prime[i])
76 {
77 p[cnt++] = i ;
78 for ( int j = i+i ; j < N ; j+=i) prime[j] = false;
79 }
80 }
81}
82LL ksm( LL a,LL b,LL mod)
83{
84 LL res = 1;
85 while (b>0)
86 {
87 if (b&1) res = (res * a) % mod;
88 b = b >> 1LL;
89 a = a * a % mod;
90 }
91 return res;
92}
93LL legendre(LL a,LL p) //勒让德符号,判断二次剩余
94{
95 if (ksm(a,(p-1)>>1,p)==1) return 1;
96 return -1;
97}
98LL pri[N],num[N];//分解质因数的底数和指数。
99int cnt; //质因子的个数
100void solve(LL n,LL pri[],LL num[])
101{
102 cnt = 0 ;
103 for ( int i = 0 ; p[i] * p[i] <= n ; i++)
104 {
105 if (n%p[i]==0)
106 {
107 int Num = 0 ;
108 pri[cnt] = p[i];
109 while (n%p[i]==0)
110 {
111 Num++;
112 n/=p[i];
113 }
114 num[cnt] = Num;
115 cnt++;
116 }
117 }
118 if (n>1)
119 {
120 pri[cnt] = n;
121 num[cnt] = 1;
122 cnt++;
123 }
124}
125LL fac[N];
126int cnt2; //n的因子的个数
127void get_fac(LL n)//得到n的所有因子
128{
129 cnt2 = 0 ;
130 for (int i = 1 ; i*i <= n ; i++)
131 {
132 if (n%i==0)
133 {
134 if (i*i!=n)
135 {
136 fac[cnt2++] = i ;
137 fac[cnt2++] = n/i;
138 }
139 else fac[cnt2++] = i;
140 }
141 }
142}
143LL find_loop(LL n)
144{
145 solve(n,pri,num);
146 LL ans = 1;
147 for ( int i = 0 ; i < cnt ; i++)
148 {
149 LL rec = 1;
150 if (pri[i]==2) rec = 3;
151 else if (pri[i]==3) rec = 8;
152 else if (pri[i]==5) rec = 20;
153 else
154 {
155 if (legendre(5,pri[i])==1)
156 get_fac(pri[i]-1);
157 else get_fac(2*pri[i]+2);
158 sort(fac,fac+cnt2);
159 for ( int j = 0 ; j < cnt2 ; j++) //挨个验证因子
160 {
161 Mat tmp = mat_ksm(M,fac[j],pri[i]); //下标从0开始,验证fac[j]为循环节,应该看fib[0]==fib[fac[j]]和fib[1]==fib[fac[j]+1]是否成立
162 tmp = mul(tmp,M1,pri[i]);
163 if (tmp.mat[0][0]==1&&tmp.mat[1][0]==1)
164 {
165 rec = fac[j];
166 break;
167 }
168 }
1 }
2 for ( int j = 1 ; j < num[i] ; j++)
3 rec *=pri[i];
4 ans = ans / gcd(ans,rec) * rec;
5 }
6 return ans;
7}
8void init()
9{
10 M.clear();
11 M.mat[0][1] = M.mat[1][0] = M.mat[1][1] = 1;
12 M1.clear();
13 M1.mat[0][0] = M1.mat[1][0] = 1;
14}
15LL get_fib(LL n,LL mod)
16{
17 if (mod==1) return 0;
18 Mat ret;
19 ret = mat_ksm(M,n-1,mod);
20 ret = mul(ret,M1,mod);
21 return (ret.mat[1][0])%mod;
22}
23LL n,P;
24int k;feibonaqi
25map< LL,LL >mp;
1LL loop[N];
2int main()
3{
4#ifndef ONLINE_JUDGE
5 freopen("code/in.txt","r",stdin);
6#endif
7 isprime();
8 int T;
9 cin>>T;
10 init();
11 int cas = 0 ;
12 while (T--)
13 {
14 scanf("%lld%d%lld",&n,&k,&P);
15 printf("Case #%d: ",++cas);
16 if (n==0||n==1)
17 {
18 printf("1\n");
19 continue;
20 }
21 loop[0] = P;
22 LL cur = n;
23 for (int i = 1; i <= k ; i++) loop[i] = find_loop(loop[i-1]);
24 for (int i = k ; i >= 0 ; i--) cur = get_fib(cur,loop[i]);
25 printf("%lld\n",cur);
26 }
27#ifndef ONLINE_JUDGE
28 fclose(stdin);
29#endif
30 return 0;
31}