POJ3420 很有趣的覆盖问题
递归推导如下:
f[n] = f[n-1] + 4*f[n-2] + 2 * [ f[n-3] + f[n-5] + f[n-7] +.... ] + 3 * [ f[n-4] + f[n-6] + f[n-8] +.... ] ; (1)
f[n - 2] = f[n-3] + 4*f[n-4] + 2 * [ f[n-5] + f[n-7] + f[n-9] +.... ] + 3 * [ f[n-6] + f[n-8] + f[n-10] +.... ] ; (2)
(1) - (2) 化简得 f[n] = f[n-1] + 5f[n-2] + f[n-3] - f[n-4]
证明略
直接用矩阵快速幂加速即可
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<stack> #include<set> #include<map> #include<algorithm> using namespace std; typedef long long int LL; const LL mt_MAXN=5;const LL mt_MAXM=5; struct Matrix { LL n,m; LL MOD; LL a[mt_MAXN][mt_MAXM]; void clear() { n=m=0; memset(a,0,sizeof(a)); } Matrix operator +(const Matrix &b)const { Matrix tmp; tmp.n=n;tmp.m=m;tmp.MOD=MOD; for(LL i=0;i<n;++i) for(LL j=0;j<m;++j) tmp.a[i][j]=(a[i][j]+b.a[i][j])%MOD; return tmp; } Matrix operator -(const Matrix &b)const { Matrix tmp; tmp.n=n;tmp.m=m;tmp.MOD=MOD; for(LL i=0;i<n;++i) for(int j=0;j<m;++j) tmp.a[i][j]=(a[i][j]-b.a[i][j])%MOD; return tmp; } Matrix operator *(const Matrix &b)const { Matrix tmp; tmp.clear(); tmp.n=n;tmp.m=b.m;tmp.MOD=MOD; for(LL i=0;i<n;++i) for(LL j=0;j<b.m;++j) for(LL k=0;k<m;++k) tmp.a[i][j]=(tmp.a[i][j]+(a[i][k]*b.a[k][j])%MOD)%MOD; return tmp; } Matrix iden() { Matrix x; memset(x.a,0,sizeof(x.a)); x.m=n;x.n=n; x.MOD=MOD; for(LL i=0;i<n;++i) x.a[i][i]=1; return x; } Matrix pow(LL t) { Matrix now; now.n=n;now.m=m;now.MOD=MOD; memset(now.a,0,sizeof(now.a)); for(LL i=0;i<n;++i) for(LL j=0;j<m;++j) now.a[i][j]=a[i][j]; for(LL i=1;i<=t;i++) now=now*now; return now; } Matrix qpow(LL t) { if(n==0)return iden(); LL i=0; Matrix now; now.n=n;now.m=m;now.MOD=MOD; now=now.iden(); while(1) { if(t%2==1)now=now*pow(i); t=t/2; if(t==0)break; i++; } return now; } }; int main() { ios::sync_with_stdio(false); //freopen("1.txt","r",stdin); //freopen("t.txt","w",stdout); while(1) { Matrix x; memset(x.a,0,sizeof(x.a)); x.n=x.m=5; x.a[0][0]=1;x.a[0][1]=5;x.a[0][2]=1;x.a[0][3]=-1; x.a[1][0]=1; x.a[2][1]=1; x.a[3][2]=1; x.a[4][3]=1; LL n,mod; cin>>n>>mod; if(n==0&&mod==0)break; if(n<1)cout<<0; else{ x.MOD=mod; Matrix ans=x.qpow(n-5); Matrix p; memset(p.a,0,sizeof(p.a)); p.MOD=mod; p.n=5;p.m=1; p.a[0][0]=95; p.a[1][0]=36; p.a[2][0]=11; p.a[3][0]=5; p.a[4][0]=1; Matrix p1=ans*p; while(p1.a[0][0]<0)p1.a[0][0]+=mod; if(n<=5)cout<<p1.a[5-n][0]; else cout<<(p1.a[0][0])%mod;} cout<<endl;} return 0; }