bzoj 3240: [Noi2013]矩阵游戏

题意:

F[1][1]=1
F[i,j]=a*F[i][j-1]+b (j!=1)
F[i,1]=c*F[i-1][m]+d (i!=1)
求F[n][m]。

题解:

假如n,m小一点的话就是一个矩乘的裸题了。
膜一发题解,发现居然可以用费马小定理优化?
其实是可以的(仅这题)
第一阶段,我们乘的是这个矩阵:

(ab01)

设这个矩阵是 A An就是:
(anb(an1+an2+1)01)

=anb(an1a1)01

an 是可以用费马小定理优化的,所以这个矩阵快速幂也可以(注意要特判a=1的情况)
然后第二阶段一样。
code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
LL mod=1000000007,a,b,c,d,p,n=0,m=0;
char s1[1000010],s2[1000010];
struct node{
    LL a[2][2],n,m;
    node() {memset(a,0,sizeof(a));}
};
node operator * (node a,node b)
{
    node ans;ans.n=a.n;ans.m=b.m;
    for(LL i=0;i<a.n;i++)
        for(LL j=0;j<b.m;j++)
            for(LL k=0;k<a.m;k++)
                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
    return ans;
}
node operator ^ (node a,LL b)
{
    node ans;ans.n=a.n;ans.m=a.m;
    for(LL i=0;i<a.n;i++) ans.a[i][i]=1;
    while(b)
    {
        if(b&1) ans=ans*a;
        a=a*a;b>>=1;
    }
    return ans;
}
void F(char*s,LL &a) {for(LL i=1;s[i];i++) a=(a*10%p+s[i]-'0')%p;}
int main()
{
    scanf("%s %s %lld %lld %lld %lld",s1+1,s2+1,&a,&b,&c,&d);
    node A;p=(a==1)?mod:mod-1;F(s2,m);
    A.n=A.m=2;A.a[0][0]=a;A.a[1][0]=b;A.a[1][1]=1;
    m-=1;(m+=p)%=p;A=A^m;
    node B;p=(A.a[0][0]==1&&c==1)?mod:mod-1;F(s1,n);
    B.n=B.m=2;B.a[0][0]=c;B.a[1][0]=d;B.a[1][1]=1;B=A*B;
    n-=1;(n+=p)%=p;B=B^n;B=B*A;
    printf("%lld",(B.a[0][0]+B.a[1][0])%mod);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值