Frightful Formula

题意

给你一个 n × n n \times n n×n 矩阵的第一行和第一列,其余的数通过如下公式推出:

F [ i , j ] = a ∗ f [ i , j − 1 ] + b ∗ f [ i − 1 , j ] + c F[i,j]=a*f[i,j-1]+b*f[i-1,j]+c F[i,j]=af[i,j1]+bf[i1,j]+c

f [ n ] [ n ] m o d ( 1 0 6 + 3 ) f[n][n] mod (10^6+3) f[n][n]mod(106+3) 的值。

数据范围

对于 100 % 100\% 100% 的数据,满足 2 ≤ n ≤ 200000 2\leq n\leq200000 2n200000,其余的数在 [ 0 , 1 0 6 ] [0,10^6] [0,106] 之间。

题解

对于 a ≠ 0 , b ≠ 0 , c = 0 a\neq 0,b \neq 0,c = 0 a=0,b=0,c=0的情况,我们考虑 f [ i ] [ j ] f[i][j] f[i][j] f [ n ] [ n ] f[n][n] f[n][n]的贡献,则原式可以理解为从 ( i , j ) (i,j) (i,j)出发,每一步可以选择向下走或向右走,向下走代价为 × b \times b ×b,向右走代价为 × a \times a ×a,到 ( n , n ) (n,n) (n,n)的所有路径的代价之和。
对于一条路径,一共要向下走 n − i n-i ni步,向右走 n − j n-j nj步。所以贡献为 a n − i ∗ b n − j a^{n-i}*b^{n-j} anibnj,路径条数为 C 2 n − i − j n − i C_{2n-i-j}^{n-i} C2nijni,乘起来即可。
我们只需要求 ∑ i = 2 n f [ 1 ] [ i ] + f [ i ] [ 1 ] \sum_{i=2}^{n}f[1][i]+f[i][1] i=2nf[1][i]+f[i][1]即可
由于路径会重复( f [ 1 ] [ i ] f[1][i] f[1][i] f [ i ] [ 1 ] f[i][1] f[i][1]是题目给的,不是自己求的),所以我们对于第一行第一步要将其向下,第一列第一步要将其向右走。
于是我们的答案就是 ∑ i = 2 n C 2 n − i − 2 n − 2 × ( f [ 1 ] [ i ] × a n − i × b n − 1 + f [ i ] [ 1 ] × a n − 1 × b n − i ) \sum_{i=2}^{n}C_{2n-i-2}^{n-2} \times (f[1][i] \times a^{n-i} \times b^{n-1} +f[i][1] \times a^{n-1}\times b^{n-i} ) i=2nC2ni2n2×(f[1][i]×ani×bn1+f[i][1]×an1×bni)
然后我们来考虑 c ≠ 0 c \neq 0 c=0的情况:
显然,我们可以发现,若我们令 g [ i ] [ j ] = f [ i ] [ j ] + k g[i][j]=f[i][j]+k g[i][j]=f[i][j]+k,且 g [ i ] [ j ] = a × g [ i ] [ j − 1 ] + b × g [ i − 1 ] [ j ] g[i][j]=a \times g[i][j-1]+b \times g[i-1][j] g[i][j]=a×g[i][j1]+b×g[i1][j],那么问题就转化为了上面的情况。
所以我们将 g [ i ] [ j ] = f [ i ] [ j ] + k g[i][j]=f[i][j]+k g[i][j]=f[i][j]+k代入,解得 k = c a + b − 1 k=\frac{c}{a+b-1} k=a+b1c。于是我们就能通过上述情况求出 g [ n ] [ n ] g[n][n] g[n][n],然后减去 k k k就是答案 f [ n ] [ n ] f[n][n] f[n][n]了。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read(){
	ll k=0,f=1;char ch;
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')k=k*10+ch-'0',ch=getchar();
	return k*f;
}
const int N=4e5+10;
const int P=1e6+3;
ll ksm(ll a,ll b){
	ll s=1;while(b){
		if(b&1)s=s*a%P;
		a=a*a%P;b>>=1;
	}
	return s;
}
ll n,f,l[N],jc[N],r[N],ans,a,b,c,k;
ll C(ll a,ll b){
	if(b>a)return 0;
	return jc[a]*ksm(jc[b],P-2)%P*ksm(jc[a-b],P-2)%P;
}
int main(){
	n=read();a=read();b=read();c=read();k=c*ksm((a+b-1)%P,P-2)%P;
	for(int i=1;i<=n;++i)l[i]=read(),l[i]=(l[i]+k)%P; 
	for(int i=1;i<=n;++i)r[i]=read(),r[i]=(r[i]+k)%P;
	jc[0]=1;
	for(int i=1;i<=2*n;++i)jc[i]=jc[i-1]*i%P;
	for(int i=2;i<=n;++i){
		ll ck=C(n*2-2-i,n-2)*(ksm(a,n-i)*ksm(b,n-1)%P*r[i]%P+ksm(a,n-1)*ksm(b,n-i)%P*l[i]%P)%P;
		ans=(ans+ck)%P;
	}
	printf("%lld\n",(ans-k+P)%P);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值