2016弱校联盟十一专场10.5 F. Fibonacci of Fibonacci
来源:互联网 发布:松下fp系列编程手册 编辑:程序博客网 时间:2024/04/29 20:25
2016弱校联盟十一专场10.5 F. Fibonacci of Fibonacci 题目链接:https://acm.bnu.edu.cn/v3/problem_show.php?pid=52322
题面描述:
题面描述:
Find FFn mod 20160519.
题目分析:
由于斐波那契数对M求模运算一定会产生循环节,而这个第一层循环节很容易找到,在找到循环节之后,利用矩阵连乘,快速幂求解。
或者把两层的循环节都找到,直接打印好表求解。
代码实现:
方法一:
#include <iostream>#include <cstdio>using namespace std;const long long M=20160519;const long long M1=26880696;const long long N=2;const int maxn=30000000;long long f[maxn];void qiuxunhuanjie(long long mod){ f[0]=0; f[1]=1; for(int i=2;i<maxn;i++) { f[i]=(f[i-1]%mod+f[i-2]%mod)%mod; } for(int i=mod-100;i<maxn;i++) { if(f[i]==1 && f[i+1]==1 && f[i+2]==2) { cout<<i<<endl; break; } }///i=26880697;}struct mat{ long long m[N][N];};mat A={ 1,1, 1,0};mat I={ 1,0, 0,1};mat multi(mat a,mat b,long long mod){ mat 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]%mod)*(b.m[k][j]%mod))%mod; c.m[i][j]%=mod; } } return c;}mat power(mat A,long long k,long long mod)//矩阵快速幂{ mat ans=I,p=A; while(k) { if(k&1)///若k为奇数, { ans=multi(ans,p,mod); k--; } k>>=1;///k=k/2; p=multi(p,p,mod); } return ans;}int main(){ ///qiuxunhuanjie(M); int T; long long n; scanf("%d",&T); while(T--) { scanf("%lld",&n); mat ans=power(A,n-1,M1); int tmp=ans.m[0][0]; //cout<<"tmp= "<<tmp<<endl; mat ans2; ans2=power(A,tmp-1,M); printf("%lld\n",ans2.m[0][0]); } return 0;}
方法二:
利用求解循环节的方法,将循环节求解出来,然后直接应用:
求循环节代码:
#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#include <math.h>#include <map>using namespace std;typedef long long LL;const int M = 2;struct Matrix{ LL m[M][M];};Matrix A;Matrix I = {1,0,0,1};Matrix multi(Matrix a,Matrix b,LL MOD){ Matrix c; for(int i=0; i<M; i++) { for(int j=0; j<M; j++) { c.m[i][j] = 0; for(int k=0; k<M; 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 k,LL MOD){ Matrix ans = I,p = a; while(k) { if(k & 1) { ans = multi(ans,p,MOD); k--; } k >>= 1; p = multi(p,p,MOD); } return ans;}int gcd(int a,int b){ return b? gcd(b,a%b):a;}const int N = 400005;const int NN = 5005;int num[NN],pri[NN];int fac[NN];bool flag[NN];int c;bool prime[N];int p[N];int k;int cnt1;int pri1[NN],num1[NN];void isprime(){ k = 0; memset(prime,true,sizeof(prime)); for(int i=2; i<N; i++) { if(prime[i]) { p[k++] = i; for(int j=i+i; j<N; j+=i) prime[j] = false; } }}LL quick_mod(LL a,LL b,LL m){ LL ans = 1; a %= m; while(b) { if(b & 1) { ans = ans * a % m; b--; } b >>= 1; a = a * a % m; } return ans;}int legendre(int a,int p){ if(quick_mod(a,(p-1)>>1,p)==1) return 1; else return -1;}void Solve(int n,int pri[],int num[],int &cnt){ cnt = 0; int t = (int)sqrt(1.0*n); for(int i=0; p[i]<=t; i++) { if(n%p[i]==0) { int a = 0; pri[cnt] = p[i]; while(n%p[i]==0) { a++; n /= p[i]; } num[cnt] = a; cnt++; } } if(n > 1) { pri[cnt] = n; num[cnt] = 1; cnt++; }}void dfs(int dept,int cnt,LL product,int pri1[],int num1[]){ if(dept == cnt) { fac[c++] = product; return; } for(int i=0; i<=num1[dept]; i++) { dfs(dept+1,cnt,product,pri1,num1); product *= pri1[dept]; }}map<int,int> mp;LL find_loop(LL n){ int cnt = 0; Solve(n,pri,num,cnt); LL ans = 1; for(int i=0; i<cnt; i++) { int record=1; if(mp.find(pri[i]) != mp.end()) { record = mp[pri[i]]; goto Test; } if(pri[i]==2) record=3; else if(pri[i]==3) record=8; else if(pri[i]==5) record=20; else { if(legendre(5,pri[i])==1) { c = 0; Solve(pri[i]-1,pri1,num1,cnt1); dfs(0,cnt1,1,pri1,num1); } else { c = 0; Solve(2*(pri[i]+1),pri1,num1,cnt1); dfs(0,cnt1,1,pri1,num1); } sort(fac,fac+c); for(int r=0; r<c; r++) flag[r] = 1; for(int k=c-1; k >= 0; k--) { if(!flag[k]) continue; Matrix a = power(A,fac[k]-1,pri[i]); int x = (a.m[0][0]%pri[i]+a.m[0][1]%pri[i])%pri[i]; int y = (a.m[1][0]%pri[i]+a.m[1][1]%pri[i])%pri[i]; if(x==1 && y==0) { record = fac[k]; } else { for(int j=0; j<=k; j++) { if(fac[k] % fac[j] == 0) flag[j] = 0; } } } mp[pri[i]] = record; }Test: for(int k=1; k<num[i]; k++) record *= pri[i]; ans=ans/gcd(ans,record)*record; } return ans;}void Init(){ A.m[0][0] = 1; A.m[0][1] = 1; A.m[1][0] = 1; A.m[1][1] = 0;}int main()///求解循环节的函数,可以求得当斐波那契数对mod=20160519取模时,循环节为:26880696 ;当对mod=26880696取模时,循环节为:746688{ //freopen("/Users/jamesqi/Desktop/in.txt","r",stdin); int T,n; Init(); mp.clear(); isprime(); scanf("%d",&T); while(T--) { scanf("%d",&n); LL ans = find_loop(n); printf("%lld\n",ans); } return 0;}
解题代码:
#include <iostream>#include <cstdio>using namespace std;const long long M=20160519;const long long M1=26880696;const long long M2=746688;long long f[M1],f2[M2];void print(){ f[0]=0; f[1]=1; f2[0]=0; f2[1]=1; for(int i=2;i<M1;i++) { f[i]=(f[i-1]%M+f[i-2]%M)%M; } for(int i=2;i<M2;i++) { f2[i]=(f2[i-1]%M1+f2[i-2]%M1)%M1; }}int main(){ int T; long long n; scanf("%d",&T); print(); while(T--) { scanf("%lld",&n); printf("%lld\n",f[f2[n%M2]]%M1); } return 0;}
0 0
- 2016弱校联盟十一专场10.5 F. Fibonacci of Fibonacci
- (2016弱校联盟十一专场10.5) F. Fibonacci of Fibonacci (暴力 + 循环节)
- 2016弱校联盟十一专场10.5 F Fibonacci of Fibonacci(矩阵快速幂 + 循环节)
- 2016弱校联盟十一专场10.5 F Fibonacci of Fibonacci(矩阵快速幂+找循环节)
- (2016 弱校联盟十一专场10.3) Similarity of Subtrees DFS + hash
- 2016弱校联盟十一专场10.3(12点场)
- 2016弱校联盟十一专场10.3,BNU52308,大模拟
- 2016弱校联盟十一专场10.2 Longest Increasing Subsequence
- [Contests]2016弱校联盟十一专场10.7
- Blocks(弱校联盟十一专场)
- UmBasketella(弱校联盟十一专场)
- 2016弱校联盟十一专场10.5(12点场) Increasing or Decreasing bnu 52325
- 2016弱校联盟十一专场10.5(12点场) Increasing or Decreasing
- 2016弱校联盟十一专场10.5 I Increasing or Decreasing(数位dp)
- 2016弱校联盟十一专场10.5---As Easy As Possible(倍增)
- Parentheses(弱校联盟十一专场)字典序
- Minimum’s Revenge(弱校联盟十一专场)
- Mr. Frog’s Problem(弱校联盟 十一专场)
- 第六周--建立 链队算法库
- 3277-City Horizon
- 贵州大学旧物交易系统
- Android 屏幕适配方案
- 护花
- 2016弱校联盟十一专场10.5 F. Fibonacci of Fibonacci
- 为cocos2dx-3.x以上版本工程指定统一通用的引擎路径
- 函数式编程语言的魅力:浅谈 Haskell
- 为什么央行新规能根治电信诈骗?专家给了3条理由
- leetcode 219. Contains Duplicate II
- Google服务器架构图解简析(转载)
- QXDM日志分析工具
- 2008-灌水
- iOS-电商常用上下左右滑动