【jzoj5047】【数字格】【数论】

题目大意

格子的第一行及第一列均是给定的:
F[k,1]=lk
F[1,k]=tk
对于其他格子,满足递推式:
F[i,j]=a*F[i,j-1]+b*F[i-1,j]+c
求F[n,n](mod 1000003)。

解题思路

对于我们发现三项互不影响,使用组合数可以o(n)算出前两项,对于第三项我们可以得出贡献等于 N2i=0N2j=0Cii+jaibjc 通过拆开组合数可以变成卷积的形式,使用fft优化。
但是我们发现这是一个正方向,对角线上c的系数和可以乘以a+b得到下一条对角线的系数和,对于正方形的另一半每一次还要用组合数减去两个多出来的数。

code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
#define Fo(i,j,k) for(int i=j;i<=k;i++)
#define Fd(i,j,k) for(int i=j;i>=k;i--)
#define For(i,j) for(int i=Begin[j];i;i=Next[i])
using namespace std;
int const Mxn=2*1e5+9,Mo=1000003,Inf=1e9;
int N,PowA[Mxn],PowB[Mxn],Fact[Mxn*2],NFact[Mxn*2];
int c(int X,int Y){
    return 1ll*Fact[X]*NFact[Y]%Mo*NFact[X-Y]%Mo;
}
int Pow(LL X,int Y){
    LL Z=1;
    while(Y){
        if(Y&1)Z=Z*X%Mo;
        X=X*X%Mo;
        Y>>=1;
    }
    return Z;
}
int main(){
    //freopen("matrix.in","r",stdin);
    //freopen("matrix.out","w",stdout);
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    LL A,B,C;
    Fact[0]=NFact[0]=Fact[1]=NFact[1]=1;
    Fo(i,2,400000)Fact[i]=1ll*Fact[i-1]*i%Mo,NFact[i]=Pow(Fact[i],Mo-2);
    while(scanf("%d%lld%lld%lld",&N,&A,&B,&C)!=EOF){
        int Ans=0,X;PowA[0]=PowB[0]=1;
        Fo(i,1,N)
            PowA[i]=A*PowA[i-1]%Mo,PowB[i]=B*PowB[i-1]%Mo;
        scanf("%d",&X);
        Fo(i,2,N){
            scanf("%d",&X);
            Ans=(Ans+1ll*PowA[N-1]*PowB[N-i]%Mo*c(N*2-i-2,N-2)%Mo*X)%Mo;
        }
        scanf("%d",&X);
        Fo(i,2,N){
            scanf("%d",&X);
            Ans=(Ans+1ll*PowA[N-i]*PowB[N-1]%Mo*c(N*2-i-2,N-2)%Mo*X)%Mo;
        }
        int Tmp=1,Ans2=1;
        Fo(i,1,N-2)
            Tmp=Tmp*(A+B)%Mo,Ans2=(Ans2+Tmp)%Mo;
        Fo(i,0,N-3)
            Tmp=(Tmp*(A+B)-1ll*(1ll*PowA[N-1]*PowB[i]%Mo+1ll*PowA[i]*PowB[N-1]%Mo)%Mo*c(N+i-2,N-2)%Mo)%Mo,Ans2=(Ans2+Tmp)%Mo;
        Ans2=(Ans2+Mo)%Mo;
        printf("%d\n",(Ans+Ans2*C)%Mo);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值