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

      

  • 相关阅读:
    Android 显示或隐藏标题栏进度条TitleProgressBar
    Android 利用Sharp样式设置文本框EditText圆角形状
    Android 中带有进度条效果的按钮(Button)
    Android 手势滑动,多点触摸放大缩小图片
    Android (Notification)消息推送机制
    Android AutoCompleteTextView控件实现类似百度搜索提示,限制输入数字长度
    Android 横向列表GridView 实现横向滚动
    Android 利用 AsyncTask 异步读取网络图片
    Android 各种功能代码收集
    Android 之 AlarmManager(定时器) 的介绍和使用
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6569230.html
Copyright © 2020-2023  润新知