bzoj2432: [Noi2011]兔农 快速幂+数论
来源:互联网 发布:淘宝网冻结 编辑:程序博客网 时间:2024/06/05 13:06
不难发现,这个题就是求斐波那契数列改化,由于有一个很强的结论,斐波那契数列取模是一个周期数列,所以我们可以去找循环节,然后找到循环节后把这第一个循环节处理出来。 其实vfk说的很详细了,注意这里mod的数不一定是个质数,我们只能用拓展欧几里得求逆元。。。。
http://vfleaking.blog.163.com/blog/static/174807634201341721051604/
#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;#define oo 2000000000000000000000LL#define ll long long#define maxn 1000100ll n,len[maxn],next[maxn];int inv[maxn],k,mod;void init(){ inv[1]=1; for(int i=2;i<k;i++) { inv[i]=(k-k/i)*inv[i]%k; }}ll gcd(ll &p,ll &q,ll x,ll y){ if(x==0){ p=1,q=1; return y; } ll r=gcd(q,p,y%x,x); p-=q*(y/x); return r;}ll gcd(ll x,ll y){ return x==0?y:gcd(y%x,x);}ll ni(ll x){ ll p,q; if(gcd(x,k)!=1)return 0; gcd(p,q,x,k); return (p%k+k)%k;}int pos[maxn],fib[maxn*6];void firstap(){ memset(pos,-1,sizeof(pos)); fib[0]=1;fib[1]=1;fib[2]=2; for(int i=3;!( fib[i-1]==1&& fib[i-2]==1);i++) { fib[i]=fib[i-1]+fib[i-2]; if(fib[i]>=k) fib[i]-=k; if(pos[fib[i]]==-1) pos[fib[i]]=i; }}struct matrix{ int a[3][3]; void cl() { memset(a,0,sizeof(a)); } void one() { memset(a,0,sizeof(a)); for(int i=0;i<3;i++) a[i][i]=1; } void A() { a[0][0]=1;a[0][1]=1;a[0][2]=0; a[1][0]=1;a[1][1]=0;a[1][2]=0; a[2][0]=0;a[2][1]=0;a[2][2]=1; } void B() { a[0][0]=1;a[0][1]=1;a[0][2]=0; a[1][0]=1;a[1][1]=0;a[1][2]=0; a[2][0]=mod-1;a[2][1]=0;a[2][2]=1; }};matrix operator *(matrix aa,matrix bb){ ll a[3][3]; for(int i=0;i<3;i++) for(int j=0;j<3;j++) { a[i][j]=0; for(int k=0;k<3;k++) { a[i][j]+=(ll)aa.a[i][k]*bb.a[k][j]%mod; a[i][j]%=mod; } } matrix cc; for(int i=0;i<3;i++) for(int j=0;j<3;j++) { cc.a[i][j]=a[i][j]; } return cc;}matrix matpow(matrix x,ll y){ matrix res;res.one(); while(y) { if(y&1){ res=res*x; } x=x*x; y>>=1; } return res;}int vis[maxn];int main(){ //freopen("rabbit20.in","r",stdin); scanf("%lld%d%d",&n,&k,&mod); for(int i=1;i<k;i++) inv[i]=ni(i); firstap(); for(int i=0;i<k;i++) { if(!inv[i]||!pos[inv[i]]) { next[i]=-1;len[i]=oo; } else { int kk=pos[inv[i]]; next[i]=(ll)fib[kk-1]*i%k; len[i]=kk+1; } } int cirs; for (cirs=1;cirs!=-1 && !vis[cirs];cirs=next[cirs]) vis[cirs]=1; matrix use; use.one(); matrix AA,BB; AA.A();BB.B(); for(int i=1;i!=cirs;i=next[i]) { if(n<len[i]) { use=use*matpow(AA,n); n=0; break; } else { use=use*matpow(AA,len[i]-1); use=use*BB; n-=len[i]; if(n==0) { break; } } } if(n>0) { int cur = cirs; ll totL = 0; matrix matC;matC.one(); do { matC = matC*matpow(AA,len[cur]-1); matC = matC*BB; totL += len[cur]; cur = next[cur]; } while (cur != cirs); use=use*matpow(matC, n / totL); n=n%totL; for(int i=cirs;;i=next[i]) { if(n<len[i]) { use=use*matpow(AA,n); break; } else { use=use*matpow(AA,len[i]-1); use=use*BB; n-=len[i]; if(n==0) { break; } } } } ll res=0; res=(ll)use.a[1][0]+(ll)use.a[2][0]; res= res%mod; cout << res << endl; return 0;}
0 0
- bzoj2432: [Noi2011]兔农 快速幂+数论
- 【矩阵快速幂】[NOI2011]兔农
- 【数论】【矩阵乘法】【NOI2011】兔农
- bzoj 2432: [Noi2011]兔农 (数论+矩阵乘法)
- [数论]矩阵快速幂
- 数论-快速幂
- 数论->快速幂
- 【数论】快速幂模板
- 数论-快速幂
- [NOIP基础数论]快速幂
- 【校内】快速幂(数论)
- 【数论】矩阵快速幂入门
- 数论——快速幂
- 【模板】【数论】快速幂和快速乘法
- bzoj 2432 [Noi2011]兔农 [矩阵]
- 矩阵乘+坑 [NOI2011] 兔农
- ACM数论之矩阵快速幂
- 数论+快速幂-hdu-4704-Sum
- hdu 1966 /poj 2066 Minimax Triangulation 计算几何
- 每天一个linux命令(46):vmstat命令
- 依赖注入
- gradle和maven有什么用?分别有什么区别?[转载来源于知乎]
- [黑马程序员]——Java乏型
- bzoj2432: [Noi2011]兔农 快速幂+数论
- Apache配置访问日志
- Python解析HDF文件
- opencv源码分析之二:cvhaartraining.cpp
- 用U盘安装Ubuntu15.04
- singleton单例模式
- ASP.NET MVC3 电影示例
- 2015年个人计划
- PHP mysqli遍历表字段名和值