[NOI2013]矩阵游戏

Bzoj 3240

传送门

据学长的话来说

这是当年noi最简单的一道题
于是抱着试一试的心态做了一做
蒟蒻QAQ


如何实现?

[NOI2013]矩阵游戏_第1张图片
由于矩阵乘法不会,只能数学必修的种数列知识推公式;
先横向推

(fx+k)=a(fx1+k)

展开就可以得到一个等比数列;
然后根据等比数列的性质可得:
fx=ax1f1+b(ax11)/(a1)

至此我们完成了将每行的最后一个用第一个表示

再根据第三个条件,同理可得:

fi+1=am1cfi+bc(am11)/(a1)+d

这里我们可以得到每一列的第i个如何用第i-1表示;

那么再将这个公式的系数看成一个整体,又是一个等比数列
我们就建立起了 fn,1f1,1 的关系

直接再用第一个公式算出 f(n,m)


注意事项

因为主人公婷婷是十分残暴的,数据范围很扎心;

那么我们知道

am=ammodφ(p)

所以在读入的时候我们需要处理一对用于乘法的n,m和一对用于幂的n,m;

因为1000000007是一个素数, φ(mod)=mod1

最后再啰嗦一句,就是逆元处理

见代码

#include 
#include 
#include 
#include 
#define LL long long 
#define mod 1000000007
using namespace std;

struct node{
    LL mul,pow;
}n,m;

LL a,b,c,d,aa,bb,ans;
LL xx,yy;

void read(node &x){
    char  ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch<='9'&&ch>='0'){
        x.mul=(x.mul*10+ch-'0')%mod;
        x.pow=(x.pow*10+ch-'0')%(mod-1);
        ch=getchar();
    }
}

LL ksm(LL x,LL y){
    LL rtn=1;
    while(y){
        if(y&1)rtn=(rtn*x)%mod;
        x=(x*x)%mod;
        y>>=1; 
    }
    return rtn; 
}

void getinv(LL a,LL b){
    if(!b){xx=1,yy=0;return;}
    getinv(b,a%b);
    LL tmp=xx;
    xx=yy;
    yy=tmp-(a/b)*yy;
}

int main()
{
#ifdef YSW
    freopen("In.txt","r",stdin);
#endif
    read(n);read(m);
    scanf("%d%d%d%d",&a,&b,&c,&d);
    aa=a,bb=b;
    if(a==1){
        a=c;
        b=((m.mul-1)*b%mod*c%mod+d)%mod;
    }
    else{
        getinv(a-1,mod);
        LL k=(b*(xx%mod+mod)%mod)%mod;
        LL t=ksm(a,(m.pow-1+mod-1)%(mod-1));
        a=t*c%mod;
        b=(k*(t-1)%mod*c%mod+d)%mod; 
    }
    if(a==1){
        a=1;
        b=b*(n.mul-1)%mod;
    }
    else{
        getinv(a-1,mod);
        LL k=(b*(xx+mod)%mod)%mod;
        LL t=ksm(a,(n.pow-1+mod-1)%(mod-1));
        a=t;
        b=k*(t-1)%mod;
    }
    LL f1=(a+b)%mod;
    if(aa==1){
        ans=(f1+(m.mul-1)*bb%mod)%mod;
    }
    else{
        getinv(aa-1,mod);
        LL k=(bb*(xx+mod)%mod)%mod;
        LL t=ksm(aa,(m.pow-1+mod-1)%(mod-1));
        aa=t;
        bb=k*(t-1)%mod;
        LL tmp=aa*f1%mod; 
        ans=(tmp+bb)%mod;
    }
    printf("%lld",ans);
    return 0; 
} 

你可能感兴趣的:(数学之美,逆元)