矩阵快速幂
矩阵快速幂,对于很大的递推式需要要用到;
贴几个题http://poj.org/problem?id=3070
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> const int M=2; const int mod=10000; struct node{ int m[M][M]; node operator*(node const &b)const{ node res; memset(res.m,0,sizeof(res.m)); for(int i=0;i<M;i++) for(int j=0;j<M;j++) for(int k=0;k<M;k++) res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod; return res; } }; node quick(node base,int b) { node t; t.m[1][1]=t.m[0][0]=1; t.m[1][0]=t.m[0][1]=0; while(b) { if(b&1) t=t*base; b>>=1; base=base*base; } return t; } int main() { node s; s.m[0][0]=s.m[0][1]=s.m[1][0]=1; s.m[1][1]=0; int n; while(~scanf("%d",&n)&&n!=-1) { if(n==0) { printf("0\n"); continue; } node sum; sum=quick(s,n); printf("%d\n",sum.m[0][1]); } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=1575
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; typedef long long ll; int n; const int mod=9973; const int M=10; struct node{ int m[M][M]; node operator*(node const &b)const{ node res; memset(res.m,0,sizeof(res.m)); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod; return res; } }; int quick(node &a,int k) { node t; memset(t.m,0,sizeof(t.m)); for(int i=0;i<n;i++) t.m[i][i]=1; while(k) { if(k&1) t=t*a; k>>=1; a=a*a; } ll sum=0; for(int i=0;i<n;i++) { sum+=t.m[i][i]; sum%=mod; } return sum; } int main() { int t; scanf("%d",&t); while(t--) { int k; scanf("%d%d",&n,&k); node a; for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a.m[i][j]); printf("%d\n",quick(a,k)); } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=2256
/*题目要求的是(sqrt(2)+sqrt(3))^2n %1024向下取整的值 (sqrt(2)+sqrt(3))^2n=((sqrt(2)+sqrt(3))^2)n=(5+2*sqrt(6))^n 改式子一定可以表示为f(x)=a[x]+b[x]*sqrt(6); 所以f(x)=f(x-1)*(5+2*sqrt(6)); 既f(x)=(5+2*sqrt(6)*(a[x-1]+b[x-1]*sqrt(6))); |5 12|*|a[n-1]|=|a[n]| |2 5 |*|b[n-1]|=|b[n]| 因此矩阵快速幂; 然后就是取数的问题了,向下取整 由(5+2*sqrt(6))^n=a[n]+b[n]*sqrt(6) (5-2*sqrt(6))^n=a[n]-b[n]*sqrt(6); 所以(5+2*sqrt(6))^n+(5-2*sqrt(6))^n=2*a[n]; 因为(5-2*sqrt(6))^n约等于0; 所以(5+2*sqrt(6))^n+0=2*a[n]; 所以(5+2*sqrt(6))^n=2*a[n]-1(向下取整) */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int M=2; const int mod=1024; const double P=sqrt((double)6); struct node{ int m[M][M]; node operator*(const node &b)const{ node res; memset(res.m,0,sizeof(res.m)); for(int i=0;i<M;i++) for(int j=0;j<M;j++) for(int k=0;k<M;k++) res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod; return res; } }; int quick(node &a,int b) { if(b==1) return 9; node t; memset(t.m,0,sizeof(t.m)); for(int i=0;i<M;i++) t.m[i][i]=1; b--; while(b) { if(b&1) t=t*a; b>>=1; a=a*a; } int suma=0; suma+=(t.m[0][0]*5+t.m[0][1]*2)%mod; return(2*suma-1)%mod; } int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); node a; memset(a.m,0,sizeof(a.m)); a.m[0][0]=5; a.m[0][1]=12; a.m[1][0]=2; a.m[1][1]=5; printf("%d\n",quick(a,n)); } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=5451
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; const int M=2; typedef long long ll; ll mod; struct node{ int m[M][M]; node operator*(node const &b)const{ node res; memset(res.m,0,sizeof(res.m)); for(int i=0;i<M;i++) for(int j=0;j<M;j++) for(int k=0;k<M;k++) res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod; return res; } }; node jksm(node base,int b){ node t; t.m[0][0]=t.m[1][1]=1; t.m[0][1]=t.m[1][0]=0; while(b){ if(b&1) t=t*base; b>>=1; base=base*base; } return t; } ll ksm(ll a,ll b,ll modd){ ll t=1; while(b){ if(b&1){ t=t*a; t%=modd; } b>>=1; a=a*a; a%=modd; } return t; } int main(){ int t; scanf("%d",&t); for(int k=1;k<=t;k++){ ll x; scanf("%lld%lld",&x,&mod); node ans; ans.m[0][0]=5; ans.m[0][1]=12; ans.m[1][0]=2; ans.m[1][1]=5; x=ksm(2ll,x,(mod-1)*(mod+1))+1; ans=jksm(ans,x); ll sum=(2*ans.m[0][0]-1)%mod; printf("Case #%d: ",k); printf("%lld\n",sum); } return 0; }
https://codeforces.com/problemset/problem/185/A
题意:求出第n年,“向上”的三角形的个数
递推式子:f[i]=3*f[i-1]+4^(n-1)-f[i-1]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define pb push_back const int inf=0x3f3f3f3f; const ll INF=1e18; const int M=2; const int mod=1e9+7; struct node{ ll m[M][M]; node operator*(node const &b)const{ node res; memset(res.m,0ll,sizeof(res.m)); for(int i=0;i<M;i++) for(int j=0;j<M;j++) for(int k=0;k<M;k++) res.m[i][j]=(res.m[i][j]+this->m[i][k]*b.m[k][j])%mod; return res; } }; void solve(ll x){ node t,sta,a; t.m[0][0]=t.m[1][1]=1; t.m[0][1]=t.m[1][0]=0; a.m[0][0]=2,a.m[0][1]=1; a.m[1][0]=0,a.m[1][1]=4; while(x){ if(x&1) t=t*a; x>>=1; a=a*a; } printf("%I64d",(t.m[0][0]+t.m[0][1]+mod)%mod); } int main(){ ll n; // scanf("%I64d",&n); while(cin>>n){ solve(n); cout<<endl; } return 0; }