您的位置:首页 > 其它

TJU-3848 Game(矩阵乘法快速幂)

2015-07-14 20:51 495 查看
一看是递推的关系,明显是矩阵乘法快速幂了。

这里举个例子,假设有3个选手,有n场比赛,得分记为Si

如果有以下关系:

S1=S1+2S3;

S2=S2+1S1+1S3;

S3=S3+5S2;

则可以用以下的矩阵乘法表示

1 1 0

(S1 S2 S3)=(S1 S2 S3)×(0 1 5)^n

2 1 1

代码写的难看,如果错误,还请指正:

#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

int nn;         //实际矩阵边长
const int N=50; //乘矩阵边长最大值
long long M;      //要模的数

struct Matrix
{
    long long f

;

    void Init0()
    {
        memset(f,0,sizeof(f));
    }
};

Matrix Matrix_mul(Matrix a,Matrix b)
{
    int i,j,k;
    Matrix ans;

    ans.Init0();
    for(i=0;i<nn;i++)
        for(j=0;j<nn;j++)
            for(k=0;k<nn;k++)
            {
                ans.f[i][j]+=a.f[i][k]*b.f[k][j];
                ans.f[i][j]%=M;
            }

    return ans;
}

Matrix QuickPow(Matrix a,int n)
{
    int i,j,k;
    Matrix ans,mul;
    mul=a;
    ans.Init0();
    for(i=0;i<nn;i++) ans.f[i][i]=1;
    while(n)
    {
        if(n&1) ans=Matrix_mul(ans,mul);
        mul=Matrix_mul(mul,mul);
        n>>=1;
    }
    return ans;
}

void work()
{
    int i,j,k,n;
    int D,S,K,ai,di;
    long long sum,ans;
    Matrix a,b;
    a.Init0();    //初始值矩阵
    b.Init0();    //系数矩阵

//读入选手数、模、比赛场数
	scanf("%d%lld%d",&nn,&M,&n);

//系数矩阵初始化
	for(i=0;i<nn;i++)
		b.f[i][i]=1;
		
	for(i=0;i<nn;i++)
	{
		scanf("%d%d%d",&D,&S,&K);
		a.f[0][D-1]=S;
		for(j=0;j<K;j++)
		{
			scanf("%d%d",&di,&ai);
			b.f[di-1][D-1]=ai;
		}
	}
	//进行矩阵乘法快速幂
	b=QuickPow(b,n);
	
/*	
	for(i=0;i<nn;i++) printf("%lld ",a.f[0][i]); printf("\n");
	printf("\n");
	
	for(i=0;i<nn;i++)
	{
		for(j=0;j<nn;j++) printf("%lld ",b.f[i][j]);
		printf("\n");
	}
*/	
	
	ans=0;
	for(j=0;j<nn;j++)
	{
		sum=0;
		for(i=0;i<nn;i++) sum=(sum+a.f[0][i]*b.f[i][j])%M;
		if(sum>ans) ans=sum;
	}
	printf("%lld\n",ans);	
}

int main()
{
    int  T;
    scanf("%d",&T);
    while(T--) work();
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: