#123456 求$f(f(n))$,$f$表示斐波那契數 $n\leq10^{100}$ 對於$1e9+7$取mod 斐波那契數在mod意義下是有循環節的, 而後zhx把他出在了noip模擬題裏, 喪心病狂,c++
丟一個paper Charles W. Campbell II. The Period of the Fibonacci Sequence Modulo j. 2007.算法
找循環節的算法大體是 把模數質n因數分解,分解爲$ p_1 ^ {k_1} * p_2^ {k_2} *...p_n^{k_n} $ 對於%n意義下的循環節就是$ lcm (mod (質因數 ^ k) 意義下的循環節 ) $
那麼後面那個怎麼求呢 有定理oop
$fib數 mod p^m$ 的最小循環節長度爲 $G(p) * p^{m - 1}$其中,$G(p)$表示$%p$的最小循環節長度spa
如今就是求$G(p)$ 對於$G(p)$咱們有以下定理code
若是$5$是模$p$的二次剩餘那麼循環節的長度是$p-1$的因子不然長度爲$2(p + 1)$ 二次剩餘及計算方法 對於小於等於5的素數特殊判斷,loop(2)=3,loop(3)=8,loop(5)=20。blog
能夠求出全部的因子,而後用矩陣快速冪來一個一個判斷,這樣時間複雜度不會很大。ip
本題模數只有一個,手玩就行了ci
#代碼get
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define int long long inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c <= '9' && c >= '0') x = x * 10 + c-'0',c = getchar(); return x *f ; } const int m1 = 1000000007; const int m2 = m1 * 2 + 2; const int m3 = m2 * 3; int n ; struct Matrix { int a[3][3]; Matrix () { memset(a,0,sizeof a); } Matrix operator * (const Matrix & p) const { Matrix ret; for(int i = 0;i <= 1;++ i) for(int j = 0;j <= 1;++ j) for(int k = 0;k <= 1;++ k) ret.a[i][j] = (ret.a[i][j] + a[i][k] * p.a[k][j]) % m1; return ret; } Matrix operator + (const Matrix & p) const { Matrix ret; for(int i = 0;i <= 1;++ i) for(int j = 0;j <= 1;++ j) for(int k = 0;k <= 1;++ k) ret.a[i][j] =(ret.a[i][j] + a[i][k] * p.a[k][j]) % m2; return ret; } }; int get1(int x) { Matrix p,q; p.a[0][0] = 1; p.a[0][1] = 1; p.a[1][0] = 1; q.a[0][1] = 1;//,q.a[1][1] = 1; for(;x;x >>= 1,p = p + p) if(x & 1) q = q + p; return q.a[0][0]; } int get2(int x) { Matrix p,q; p.a[0][0] = 1; p.a[0][1] = 1; p.a[1][0] = 1; q.a[0][1] = 1; for(;x;x >>= 1,p = p * p) if(x & 1) q = q * p; return q.a[0][0]; } char s[100007]; struct bign { int z[100007],l; void init() { memset(z,0,sizeof(z)); scanf("%s",s + 1); l = strlen(s + 1); for(int i = 1;i <= l;i ++) z[i] = s[l - i + 1] - '0'; } int operator % (const long long & a) const { int b = 0; for (int i = l;i >= 1;i --) b = (b * 10 + z[i]) % a; return b; } }z; main() { int t = read(); bign num; while(t --) { num.init(); n = num % m3; n = get1(n); printf("%lld\n",get2(n)); } return 0; } /* */