由vijos1067 联想到的矩阵乘法

来源:互联网 发布:微信交友公众号源码 编辑:程序博客网 时间:2024/05/01 06:03

最近做动态规划时,遇到了一道题,需要矩阵乘法,这里总结一下(感谢 @The_useless)
首先,这里写图片描述
即对于C矩阵来说,c[i][j]=A矩阵[i]行与B矩阵[j]列的乘积之和,Code:

matrix operator *(matrix a,matrix b){    matrix c;    c.init(a.n,b.m);    fo(i,1,c.n)        fo(j,1,c.m)            fo(k,1,a.m)                c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j])%MOD;    return c;   }

知道了这些就可以做题了.

题目大意:
一条长度为n的道路,每一次可以向前走1或k,询问走到n一共有多少方案.
数据范围:
第一行是闪烁技能的等级k(1<=k<=10)
第二行是监狱的个数n(1<=n<=2^31-1)

分析:
我们可以很快速的求出状态转移方程:

fo(i,1,n)  fo(j,1,k-1)      f[i]=(f[i]+f[j]);

我们发现由于n的值实在太大了,毫无疑问会超时,而k<=10,考虑k.根据矩阵乘法的性质,我们很容易可以得出,这是一道矩阵乘法可以解出的题目;
所以我们需要构造一个矩阵,使它与答案相乘等于下一次.
这里有两种构造方法,
若ans[1][k]

    unit.init(k,k);    fo(i,1,k-1) unit.num[i][i+1]=1;    fo(i,1,k) unit.num[k][i]=1; 

若ans[k][1] 反过来就好了
最后,记得单位矩阵(蒟蒻楼主刚刚知道),即一个矩阵p,与另一个任意矩阵q,p*q=q;
对角线全为1就好

最后附上code:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<cstdlib>#include<queue>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int MOD=7777777,MAXN=15;typedef long long ll;struct matrix{    ll n,m,num[MAXN][MAXN];    void init(int x,int y){        n=x;m=y;        memset(num,0,sizeof(num));    }};matrix operator *(matrix a,matrix b){    matrix c;    c.init(a.n,b.m);    fo(i,1,c.n)        fo(j,1,c.m)            fo(k,1,a.m)                c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j])%MOD;    return c;   }int n,k;matrix Solve(){    matrix unit,ans;    unit.init(k,k);    fo(i,1,k-1) unit.num[i+1][i]=1;    fo(i,1,k) unit.num[i][k]=1;    ans.init(k,k); //ans是单位矩阵     fo(i,1,k) ans.num[i][i]=1;    for(int tot=n-k+1;tot;tot>>=1)    {        if(tot&1) ans=ans*unit;        unit=unit*unit;    }    return ans;}matrix ans; int main(){    scanf("%d%d",&k,&n);    ans.init(1,k);ans.num[1][1]=1;    fo(i,2,k)        fo(j,1,i-1)            ans.num[1][i]=(ans.num[1][i]+ans.num[1][j])%MOD;    ans=ans*Solve();//  fo(i,1,k) printf("%lld ",ans.num[1][i]);    printf("%lld",ans.num[1][k]);    return 0;}
0 0
原创粉丝点击