JZOJ链接
《论比赛时不对拍大数据的危害》
公式推错了,类型没开大,于是就——
咳咳,来说题解。
首先直接每一项推
O(N2)
明显是不现实的。
那不怕苦不怕累的话就可以考虑开Excel表找规律。
其实观察表也能想到,我们可以计算第一行,第一列的数对答案的影响。
尝试转化原题:
一些数字从
F1,i,Fi,1(1≤i≤N)
走向
FN,N
,从一个格子向右走,数值就乘上A,向下走就乘上B。
可以发现他们不管怎么走,A与B的指数都是不变的
这些数字对答案的贡献就应该是:
Fi,j
*
AX
(X为i到N的列差值)
BY
(Y为j到N的行差值)路径方案数
方案数通过推断,找规律的话也容易得出:
从
Fi,j
到
FN,N
的方案数为:
Cn−in∗2−i−j
题目要求对10^9+7取模,而方案数的转化计算中涉及到除法,于是我们就需要逆元了!
因为10^9+7是一个质数,逆元可以利用费马小定理来做
于是答案自然出来了,先预处理A.B的若干次方,阶乘以及逆元,
O(N)
处理即可。
小细节的话注意开Int64,如果N=1的话要输出第一项(这也是第一项唯一有用的地方=_=)
代码有点乱
const
moder=1000000007;
var
r,c,fc,ny,a,b:array[0..200000] of int64;
n,i:longint;
ans,sum,aa,bb:int64;
function qpow(x,pow:int64):int64;
begin
qpow:=1;
while pow>0 do
begin
if (pow and 1)=1 then qpow:=qpow*x mod moder;
x:=x*x mod moder;
pow:=pow shr 1;
end;
exit(qpow mod moder);
end;
begin
readln(n,aa,bb);
for i := 1 to n do read(c[i]);
for i := 1 to n do read(r[i]);
fillchar(fc,sizeof(fc),0);fc[0]:=1;
for i := 1 to n*2 do
fc[i]:=fc[i-1]*i mod moder;
a[0]:=1;b[0]:=1;ny[0]:=1;
for i := 1 to n do
begin
a[i]:=(a[i-1]*aa) mod moder;
b[i]:=(b[i-1]*bb) mod moder;
ny[i]:=qpow(fc[i],moder-2);
end;
ans:=0;
for i :=2 to n do
begin
sum:=(((((r[i]*fc[n*2-i-2] mod moder)*(ny[n-i]*ny[n-2] mod moder) mod moder)*(a[n-i]*b[n-1] mod moder)) mod moder)
+((((c[i]*fc[n*2-i-2] mod moder)*(ny[n-i]*ny[n-2] mod moder) mod moder)*(a[n-1]*b[n-i] mod moder)) mod moder)) mod moder;
ans:=(ans+sum) mod moder;
end;
writeln(ans);
end.