1. 程式人生 > >luogu P1397 [NOI2013]矩陣遊戲

luogu P1397 [NOI2013]矩陣遊戲

amp cpp while org 傳送門 con 數列求和 space inline

傳送門

題目中那兩個遞推式顯然可以寫成矩乘的形式,然後十進制快速冪即可.這裏不再贅述

只有兩個遞推式,我們可以考慮一波推式子,首先第一行的元素應該分別是\(1,a+b,a^2+ab+b,a^3+a^2b+ab+b...a^{m-1}+b\sum_{i=0}^{m-2}a^i\)

然後這樣子推下去,第二行最後一個元素為\(a^{2(m-1)}c+a^{m-1}bc\sum_{i=0}^{m-2}a^i+a^{m-1}d+b\sum_{i=0}^{m-2}a^i\)

同理,第三行最後一個元素為\(a^{3(m-1)}c^2+a^{2(m-1)}bc^2\sum_{i=0}^{m-2}a^i+a^{2(m-1)}cd+a^{m-1}bc\sum_{i=0}^{m-2}a^i+a^{m-1}d+b\sum_{i=0}^{m-2}a^i\)

...

所以我們可以歸納得到\(f_{n,m}\)\[a^{n(m-1)}c^{n-1}+a^{m-1}d\sum_{i=0}^{n-2}(a^{m-1}c)^i+b\sum_{i=0}^{m-2}a^i\sum_{j=0}^{n-1}(a^{m-1}c)^j\]

然後等比數列求和公式一套就完事了

註意\(a=1,c=1\)的情況

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define uLL unsigned long long
#define il inline

using namespace std;
const int N=1e6+10,mod=1e9+7;
il int rd()
{
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
int inv(int a){return fpow(a,mod-2);}
int qh(int a,int n){return a==1?n:1ll*(1-fpow(a,n)+mod)*inv(1-a+mod)%mod;}
char cc[N],ss[N];
int l1,l2,n,m,nn,mm,a,b,c,d,pa,sa,sb,sc,ans,ac;

int main()
{
    scanf("%s%s",cc+1,ss+1);
    l1=strlen(cc+1),l2=strlen(ss+1);
    a=rd()%mod,b=rd()%mod,c=rd()%mod,d=rd()%mod;
    for(int i=1;i<=l1;++i) n=(1ll*n*10+cc[i]-'0')%(mod-1),nn=(1ll*nn*10+cc[i]-'0')%mod;
    for(int i=1;i<=l2;++i) m=(1ll*m*10+ss[i]-'0')%(mod-1),mm=(1ll*mm*10+ss[i]-'0')%mod;
    pa=fpow(a,(m-1+mod-1)%(mod-1));
    sa=a>1?qh(a,m-1):mm-1;
    ac=1ll*pa*c%mod;
    sb=ac>1?qh(ac,n-1):nn-1;
    sc=ac>1?qh(ac,n):nn;
    ans=1ll*fpow(c,(n-1+mod-1)%(mod-1))*fpow(pa,n)%mod;
    if(n>1) ans=(ans+1ll*pa*sb%mod*d%mod)%mod;
    ans=(ans+1ll*sc*sa%mod*b%mod)%mod;
    printf("%d\n",ans);
    return 0;
}

luogu P1397 [NOI2013]矩陣遊戲