POJ3420 递推+矩阵快速幂

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;
}