数字格

题目描述

菁菁堂有一块数字格,那是王解体最喜欢去的地方。
传说中,这条气势磅礴的数字格,有N行N列,每一个格子里均有一个数。
敢于挑战自己的王解体决定来挑战这道通过率为百分之九十九的题目。
格子的第一行及第一列均是给定的:
F[k,1]=l[k](k=1,2,3,,N)
F[1,k]=t[k](k=1,2,3,,N)
对于其他格子,满足递推式:
F[i,j]=a*F[i,j-1]+b*F[i-1,j]+c
不出所料,当王解体能得到 F[n,n](mod 1000003)时,通过率将达到百分之百。

机智法

容易知道只需要考虑常数c的影响。
一条斜线一条斜线的扫。
c的贡献和每次乘a+b。
过半后会超出两端,单独计算减去即可。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int mo=1000003,maxn=400000+10;
int fac[maxn],inv[maxn],L[maxn],T[maxn],mia[maxn],mib[maxn];
int i,j,k,l,t,n,m,ans,sum,num,a,b,c;
int quicksortmi(int x,int y){
    if (!y) return 1;
    int t=quicksortmi(x,y/2);
    t=(ll)t*t%mo;
    if (y%2) t=(ll)t*x%mo;
    return t;
}
int C(int n,int m){
    if (n<m||m<0) return 0;
    return (ll)fac[n]*inv[m]%mo*inv[n-m]%mo;
}
int main(){
    freopen("matrix.in","r",stdin);freopen("matrix.out","w",stdout);
    fac[0]=1;
    fo(i,1,maxn-10) fac[i]=(ll)fac[i-1]*i%mo;
    inv[maxn-10]=quicksortmi(fac[maxn-10],mo-2);
    fd(i,maxn-11,0) inv[i]=(ll)inv[i+1]*(i+1)%mo;
    while (scanf("%d%d%d%d",&n,&a,&b,&c)!=EOF){
        if (n==1){
            scanf("%d%d",&t,&t);
            t%=mo;
            printf("%d\n",t);
            continue;
        }
        mia[0]=mib[0]=1;
        fo(i,1,n){
            mia[i]=(ll)mia[i-1]*a%mo;
            mib[i]=(ll)mib[i-1]*b%mo;
        }
        ans=0;
        fo(i,1,n){
            scanf("%d",&t);
            if (i==1) continue;
            (ans+=(ll)C(n-2+n-i,n-i)*mia[n-1]%mo*mib[n-i]%mo*t%mo)%=mo;
        }
        fo(i,1,n){
            scanf("%d",&t);
            if (i==1) continue;
            (ans+=(ll)C(n-2+n-i,n-i)*mia[n-i]%mo*mib[n-1]%mo*t%mo)%=mo;
        }
        sum=num=1;
        fo(i,1,n-2){
            num=(ll)num*(a+b)%mo;
            (sum+=num)%=mo;
        }
        fo(i,1,n-2){
            num=(ll)num*(a+b)%mo;
            j=n-i+1;k=2;
            //t=(ll)C(n-j+n-k,n-j)*mib[n-j]%mo*mia[n-k]%mo;
            t=(ll)C(n-j+n-k,n-j)*mib[n-j]%mo*mia[n-k]%mo*a%mo;
            (num-=t)%=mo;
            j=2;k=n-i+1;
            //t=(ll)C(n-j+n-k,n-j)*mib[n-j]%mo*mia[n-k]%mo;
            t=(ll)C(n-j+n-k,n-j)*mib[n-j]%mo*mia[n-k]%mo*b%mo;
            (num-=t)%=mo;
            (sum+=num)%=mo;
        }
        (ans+=(ll)sum*c%mo)%=mo;
        (ans+=mo)%=mo;
        printf("%d\n",ans);
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值