您的位置:首页 > 产品设计 > UI/UE

【矩阵乘法再实践】HDU 2604——queuing

2013-02-22 16:25 344 查看
题目:点击打开链接

首先,这是一个递推问题。mm结尾的只能由fm结尾的或者mm结尾的推来。以mf结尾的只能由mm结尾的推来,以fm结尾的只能由mf或者ff推来,以ff结尾的只能由mf推来。

F(n)=F(n-1)+F(n-3)+F(n-4)。可是正常用大数的话会TLE。后来查阅DISCUSS得知应该使用矩阵乘法。

其中1——4是已知的。

其中这个A矩阵是要构建的,一般是通过0-1阵,达到下图的目的,构阵方式不唯一。



构完阵后,将目标值-4,然后进行二分幂优化,再手动把前四加上,还是稍微有点晕的,毕竟数学略拙计。。

另外附两个较为清楚的大神链接:

矩阵乘法的方法 DP的方法

#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;

class Mat
{
public:
    __int64 mat[10][10];
};

int n=4;     //维度,即矩阵A的行数
int MOD;//好多问题要求给出取余之后的数字
Mat E;
int f[5]={0,2,4,6,9};
void initE()
{
	for(int i=0;i<10;i++)
		E.mat[i][i]=1;
}

Mat operator*(Mat a,Mat b)
{
    int i,j,k;
    Mat c;
    for (i=0;i<n;i++)
    {
        for (j=0;j<n;j++)
        {
            c.mat[i][j] = 0;
            	for (k=0;k<n;k++)
                	c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%MOD;
           	    c.mat[i][j]%=MOD;
        }
    }
    return c;
}

Mat operator+(Mat a,Mat b)
{
    Mat c;
    int i,j;
    for (i=0;i<n;i++)
    {
        for (j=0;j<n;j++)
            c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD;
    }
    return c;
}

Mat operator^(Mat a,int x)  
{  
     Mat p = E,q = a;  
     while (x>=1)  
     {  
         if(x%2==1)  
             p = p*q;  
         x/=2;  
         q = q*q;  
     }  
     return p;  
}
Mat solve(Mat a,int p)  
 {  
     if(p==1)  
         return a;
     else if(p&1)  
         return (a^p)+solve(a,p-1);  
     else  
         return ((a^(p>>1))+E)*solve(a,p>>1);  
 }  
 
 
 int main()
 {
 	int length,mod;
 	while(cin>>length>>MOD)
 	{
 		initE();
		Mat a;
		memset(a.mat,0,sizeof(a.mat));
 		a.mat[0][0]=a.mat[0][2]=a.mat[0][3]=a.mat[1][0]=a.mat[2][1]=a.mat[3][2]=1;
		 
	 	if(length<=4)
	 	{
	 		cout<<f[length]%MOD<<endl;
	 		continue;
	 	}
	 	Mat x;
	 	
	 	x=a^(length-4);
	 	
	 	int ans=0;
	 	
	 	ans=(x.mat[0][0]*9+x.mat[0][1]*6+x.mat[0][2]*4+x.mat[0][3]*2);
	 	cout<<ans%MOD<<endl;
 	}
 	return 0;
 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: