快速入门视频: av56433157
1> p1926 斐波那契
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; long long n; const int mod=1000000007; long long nw[2][2],ans[2][2]; long long t[2][2]; void mul1() { memset(t,0,sizeof(t)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) t[i][j]+=(ans[i][k]*nw[j][k])%mod; for(int i=0;i<2;i++) for(int j=0;j<2;j++) ans[i][j]=t[i][j]; } void mul2() { memset(t,0,sizeof(t)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) t[i][j]+=(nw[i][k]*nw[j][k])%mod; for(int i=0;i<2;i++) for(int j=0;j<2;j++) nw[i][j]=t[i][j]; } void mul3() { long long as=0; for(int i=0;i<2;i++) as=(as+ans[0][i])%mod; printf("%lld ",as); } int main() { scanf("%lld",&n); n-=2; if(n<=0) { printf("1 "); return 0; } nw[0][0]=nw[1][0]=nw[0][1]=1; ans[0][0]=ans[1][1]=1; while(n) { if(n&1) mul1(); n>>=1,mul2(); } mul3(); return 0; }
2>广义斐波那契数列
这道题中的乘法,会爆ll,
所以只能用pow_add(),具体见代码
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; long long a,c,a0,n,mod,g; long long ans[3][3],nw[3][3],t[3][3]; long long pow_add(long long x,long long y) { long long ans=0; while(y) { if(y&1) ans=(ans+x)%mod; x=(x+x)%mod; y>>=1; } return ans; } void mul1() { memset(t,0,sizeof(t)); for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) t[i][j]=(t[i][j]+pow_add(ans[i][k],nw[k][j]))%mod; for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans[i][j]=t[i][j]; } void mul2() { memset(t,0,sizeof(t)); for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) t[i][j]=(t[i][j]+pow_add(nw[i][k],nw[k][j]))%mod; for(int i=0;i<3;i++) for(int j=0;j<3;j++) nw[i][j]=t[i][j]; } int main() { scanf("%lld%lld%lld%lld%lld%lld",&mod,&a,&c,&a0,&n,&g); c%=mod,a%=mod,a0%=mod; long long a1=(pow_add(a,a0)+c)%mod; if(n==1) printf("%d ",a1%g); if(n<2) return 0; n-=2; ans[0][0]=a,ans[0][2]=ans[1][0]=ans[2][2]=1; nw[0][0]=a,nw[0][2]=nw[1][0]=nw[2][2]=1; while(n) { if(n&1) mul1(); n>>=1,mul2(); } printf("%d ",(pow_add(a1,ans[0][0])+pow_add(a0,ans[0][1])+pow_add(c,ans[0][2]))%mod%g); return 0; }
3>ch30摆花
用矩阵快速幂加速dp,优化时间复杂度和空间复杂度
60->100
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; int n,m; const int N=103,mod=1e9+7; long long nw[N][N],ans[N],t[N][N],tt[N]; void mul1() { memset(tt,0,sizeof(tt)); for(int i=0;i<=n;i++) for(int k=0;k<=n;k++) tt[i]=(tt[i] +nw[i][k]*ans[k]%mod) %mod; for(int i=0;i<=n;i++) ans[i]=tt[i]; } void mul2() { memset(t,0,sizeof(t)); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) for(int k=0;k<=n;k++) t[i][j]=(t[i][j] +nw[i][k]*nw[k][j]%mod)%mod; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) nw[i][j]=t[i][j]; } void mul3() { long long as=0; for(int i=0;i<=n;i++) as=(as+ans[i])%mod; printf("%lld ",as); } int main() { scanf("%d%d",&m,&n); int x; for(int i=0;i<=n;i++) nw[i][0]=nw[0][i]=1; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%1d",&x); nw[i][j]=x^1; } ans[0]=1; while(m) { if(m&1) mul1(); m>>=1,mul2(); } mul3(); return 0; }