HDU 3978 斐波那契循环节
来源:互联网 发布:手机行业进销存软件 编辑:程序博客网 时间:2024/05/22 22:07
题意:给出f(f(f...f(n)...)) 总共嵌套k次。问最后模p的值是多少。
首先应该明白的是这个题有循环节的。一个数模N的循环节就是这个数分解成素因子乘积的形式p1^a1*p2^a2*p3^a3...后,斐波那契模pi^ai的循环节的最大公约数。
那么一个素数的k次幂的循环节=斐波那契模上这个素数的循环节乘上p^(k-1)。
而一个素数p的循环节 如果p>5并且是5的二次剩余,那么循环节就是(p-1)的因子,否则就是2*(p+1)的因子。所以2 3 5 的时候需要特判一下。
知道这些就能求每一次嵌套的循环节了,通过矩阵连乘即可得出答案。
#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define maxn 20050bool isprime[maxn];int prime[maxn],nprime,mod[maxn],M;int primeloop[maxn];void getprime(){ long long i,j; memset(isprime,1,sizeof(isprime)); nprime=0; for(i=2; i<maxn; i++) if(isprime[i]) { prime[nprime++]=i; for(j=i*i; j<maxn; j+=i) isprime[j]=0; }}int factor[100][2],tol,fac[100][2],numfac;void findfac(int n,int f[][2],int &t){ int x=n,l=(int)sqrt(1.0*n); t=0; for(int i=0; i<50; i++) f[i][0]=f[i][1]=0; for(int i=0; prime[i]<=l; i++) if(x%prime[i]==0) { f[t][0]=prime[i]; while(x%prime[i]==0) f[t][1]++,x/=prime[i]; t++; } if(x>1) f[t][0]=x,f[t++][1]++;}const int MAX=2;typedef struct{ long long m[MAX][MAX];} Matrix;Matrix P,I;Matrix matrixmul(Matrix a,Matrix b) //矩阵乘法{ int i,j,k; Matrix c; for (i=0; i<MAX; i++) for (j=0; j<MAX; j++) { c.m[i][j]=0; for(k=0; k<MAX; k++) c.m[i][j]+=((a.m[i][k]%M)*(b.m[k][j]%M))%M; c.m[i][j]%=M; } return c;}void quickpow(int n,int &x,int &y){ Matrix m=P,b=I; while(n) { if(n&1) b=matrixmul(b,m); n>>=1,m=matrixmul(m,m); } x=b.m[0][0],y=b.m[1][0];}int gcd(int a,int b){ return b?gcd(b,a%b):a;}int exp_mod(int a,int b,int c){ int ans=1; a%=c; while(b) { if(b&1) ans=ans*a%c; b>>=1,a=a*a%c; } return ans;}int minloop,ff[maxn],numff;void dfs(int num,int s=1){ if(num==numfac) { ff[numff++]=s; return; } for(int i=0; i<=fac[num][1]; i++) dfs(num+1,s),s*=fac[num][0];}int getPrimeLoop(int p){ if(p==2) return 3; if(p==3) return 8; if(p==5) return 20; M=p; if(exp_mod(5,(p-1)>>1,p)==1) p--; else p=2*p+2; findfac(p,fac,numfac); minloop=1e9; numff=0; dfs(0,1); sort(ff,ff+numff); int x,y; for(int i=1; i<numff; i++) { quickpow(ff[i]-1,x,y); if(x==0&&y==1) return ff[i]; }}int getLoop(int p,int k){ int ret; if(p>19583) ret=getPrimeLoop(p); else ret=primeloop[p]; for(int i=0; i<k-1; i++) ret*=p; return ret;}int getmod(int n){ findfac(n,factor,tol); int ret=1,tem; for(int i=0; i<tol; i++) tem=getLoop(factor[i][0],factor[i][1]),ret=ret/gcd(ret,tem)*tem; return ret;}int main(){ int t,ca=0,p,n,k,x,y; getprime(); P.m[0][0]=P.m[0][1]=P.m[1][0]=1,P.m[1][1]=0; I.m[0][0]=I.m[1][1]=1,I.m[1][0]=I.m[0][1]=0; for(int i=0; i<2250; i++) primeloop[prime[i]]=getPrimeLoop(prime[i]); scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&k,&p); mod[0]=p; for(int i=1; i<=k; i++) mod[i]=getmod(mod[i-1]); for(int i=k; i>=0; i--) { if(i<k) n%=mod[i+1]; M=mod[i],quickpow(n,x,y),n=x; } printf("Case #%d: %d\n",++ca,n); } return 0;}
- HDU 3978 斐波那契循环节
- hdu-2814-Interesting Fibonacci-斐波那契循环节
- HDU 4794 Arnold 斐波那契数列循环节
- HDU 4794 斐波那契数列循环节
- HDU 3977 求斐波那契循环节
- hdu 1021 斐波那契数列取模(循环节)
- HDU 2814 斐波那契数列的循环节问题
- HDU 3977 Evil teacher(斐波那契数列循环节)
- HDU 2814 斐波那契循环节+欧拉函数降幂
- hdu 5451 Best Solver -广义斐波那契+矩阵快速幂+共轭构造+循环节
- [斐波那契循环节 数学技巧] HDU 3977 Evil teacher
- HDU 5674 Function(斐波那契模数列循环节)
- HDU 2814 斐波那契循环节+欧拉函数降幂
- NEFU 115 斐波那契的整除 循环节
- UVA11582Colossal Fibonacci Numbers!(斐波那契找循环节)
- HDU2813Interesting Fibonacci(斐波那契数列+循环节)
- 【2012-12】【斐波那契循环节】Evil Teacher
- hdu5451 矩阵乘法+斐波那契 + 循环节
- [K/3Cloud]将JSON字符串反序列化为C#动态对象
- Coursera推荐系统课笔记之eclipse与lenskit的设置
- 聊聊Windows程序中的"\r"和"\n"
- mmap详解
- 已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde 的个数,如果没有返回0,有的话返回子字符串的个数。
- HDU 3978 斐波那契循环节
- OSX:制作安装包的工具们
- 基于mini2440的RTC读写(裸机)
- 奇偶数入座
- 网络IPC:套接字
- C语言中的经典小程序3
- 第四篇 随笔(小诗)
- [K/3Cloud] 树形单据体的应用说明
- LightSwitch登录界面如何设置背景