今天将来学习如何求广义Fibonacci数列的循环节。
问题:给定,满足,求的循
环节长度。
来源:http://acdreamoj.sinaapp.com/ 1075题
分析:我们知道矩阵的递推关系如下
然后继续有
那么,现在的问题就转化为求最小的,使得
所以我们可以先找出符合条件的一个,然后枚举它的因子,找最小的。设
为了好解决问题,我们需要对矩阵进行相似对角化,即,我们先来求的特征值。
解得的特征值为
也就是说的相似对角矩阵为
因为我们知道,所以当时,, 由于
继续得到
设,那么分情况讨论:
(1)是模的二次剩余,由费马小定理得时,
(2)是模的二次非剩余,则有
根据欧拉准则有
那么继续得到
然后由费马小定理有,同理有
所以,当时,
(3)时,由于不存在,所以无法完成相似对角化,好在这种情况不存在。
所以综上所述:
是模的二次剩余时,枚举的因子
是模的二次非剩余时,枚举的因子
找最小的因子,使得
成立。
代码:
- #include <iostream>
- #include <string.h>
- #include <algorithm>
- #include <stdio.h>
- #include <math.h>
- using namespace std;
- typedef long long LL;
- const int N = 2;
- const LL MOD = 1000000007;
- LL fac[2][505];
- int cnt,ct;
- LL pri[6] = {2, 3, 7, 109, 167, 500000003};
- LL num[6] = {4, 2, 1, 2, 1, 1};
- struct Matrix
- {
- LL m[N][N];
- } ;
- Matrix A;
- Matrix I = {1, 0, 0, 1};
- Matrix multi(Matrix a,Matrix b)
- {
- Matrix c;
- for(int i=0; i<N; i++)
- {
- for(int j=0; j<N; j++)
- {
- c.m[i][j] =0;
- for(int k=0; k<N; k++)
- {
- c.m[i][j] += a.m[i][k] * b.m[k][j];
- c.m[i][j] %= MOD;
- }
- }
- }
- return c;
- }
- Matrix power(Matrix A,LL n)
- {
- Matrix ans = I, p = A;
- while(n)
- {
- if(n & 1)
- {
- ans = multi(ans,p);
- n--;
- }
- n >>= 1;
- p = multi(p,p);
- }
- return ans;
- }
- LL quick_mod(LL a,LL b)
- {
- LL ans = 1;
- a %= MOD;
- while(b)
- {
- if(b & 1)
- {
- ans = ans * a % MOD;
- b--;
- }
- b >>= 1;
- a = a * a % MOD;
- }
- return ans;
- }
- LL Legendre(LL a,LL p)
- {
- LL t = quick_mod(a,(p-1)>>1);
- if(t == 1) return 1;
- return -1;
- }
- void dfs(int dept,LL product = 1)
- {
- if(dept == cnt)
- {
- fac[1][ct++] = product;
- return;
- }
- for(int i=0; i<=num[dept]; i++)
- {
- dfs(dept+1,product);
- product *= pri[dept];
- }
- }
- bool OK(Matrix A,LL n)
- {
- Matrix ans = power(A,n);
- return ans.m[0][0] == 1 && ans.m[0][1] == 0 &&
- ans.m[1][0] == 0 && ans.m[1][1] == 1;
- }
- int main()
- {
- fac[0][0] = 1;
- fac[0][1] = 2;
- fac[0][2] = 500000003;
- fac[0][3] = 1000000006;
- LL a,b,c,d;
- while(cin>>a>>b>>c>>d)
- {
- LL t = a * a + 4 * b;
- A.m[0][0] = a;
- A.m[0][1] = b;
- A.m[1][0] = 1;
- A.m[1][1] = 0;
- if(Legendre(t,MOD) == 1)
- {
- for(int i=0; i<4; i++)
- {
- if(OK(A,fac[0][i]))
- {
- cout<<fac[0][i]<<endl;
- break;
- }
- }
- }
- else
- {
- ct = 0;
- cnt = 6;
- dfs(0,1);
- sort(fac[1],fac[1]+ct);
- for(int i=0;i<ct;i++)
- {
- if(OK(A,fac[1][i]))
- {
- cout<<fac[1][i]<<endl;
- break;
- }
- }
- }
- }