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

来源:互联网 发布:linux中grep命令 编辑:程序博客网 时间:2024/05/20 23:32

一看是递推的关系,明显是矩阵乘法快速幂了。

这里举个例子,假设有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[N][N];    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;}


0 0
原创粉丝点击