您的位置:首页 > 其它

JZOJ 4709 Matrix【NOIP2016提高A组模拟8.17】

2016-08-17 20:01 489 查看

Matrix

题目描述



数据范围



题解

这一题,挺水的,比赛时一眼就看出了题解,经过验证后证明我的做法是对的,切掉。O(∩_∩)O~~

我们单独考虑第一列和第一行上的数但答案的单独贡献。

首先,(1,1)这个位置上的数对答案是没有贡献的,除非,n=1,呵呵。

然后,某个位置对答案的贡献就等于该位置所有走到(n,n)的方案的总贡献。

一次往右走,我们可以视为乘a,向下走,我们可以视为乘b,其实某个位置走到(n,n)的每种方案给答案的贡献都是一样的,因为向右、下走的次数都相等。

经过推算,可得出以下显然的结论:

(i,1)所有走到(n,n)的每种方案的贡献为li * an−1 * bn−i

(1,i)所有走到(n,n)的每种方案的贡献为ti * an−i * bn−1

相信大家知道,从(i,l)走到(n,m)的总方案为Cn−in+m−i−l。(这很显然

然后从(i,1)或从(1,i)出发第一步有限制,必须先走到(i,2)或(2,i),之后最可以向下或向右走动了,所以从(i,1)或从(1,i)出发的方案数其实等于从(i,2)或从(2,i)走到(n,n)的方案数,即为

Cn−i2∗n−i−2=(2∗n−i−2)!(n−2)!∗(n−i)! mod (109+7)

109+7 显然是个素数,于是预处理出k!及其逆元,一个位置对答案的贡献即为 从此位置出发走到(n,n)的方案数 * 每种方案对答案的贡献,这样就可以O(n)算出答案了。

Code(Pascal)

const
mo=1000000007;
var
n,i:longint;
a,b,ans,kkk:int64;
ycl,ny:array[0..300000] of int64;
h,z,aa,bb:array[0..150000] of int64;
function ksm(o,t:int64):int64;
var
cqy:int64;
begin
cqy:=1;
while t>0 do
begin
if t mod 2=1 then cqy:=(cqy*o) mod mo;
o:=(o*o) mod mo;
t:=t div 2;
end;
exit(cqy);
end;
begin
readln(n,a,b);
for i:=1 to n do
read(z[i]);
readln;
for i:=1 to n do
read(h[i]);
ycl[0]:=1;
for i:=1 to 2*n do
ycl[i]:=ycl[i-1]*i mod mo;
aa[0]:=1;
for i:=1 to n do
aa[i]:=(aa[i-1]*a) mod mo;
bb[0]:=1;
for i:=1 to n do
bb[i]:=(bb[i-1]*b) mod mo;
for i:=1 to n do
ny[i]:=ksm(ycl[i],mo-2);
ny[0]:=1;
ans:=0;
for i:=2 to n do
begin
kkk:=h[i]*ycl[2*n-i-2] mod mo;
kkk:=kkk*(ny[n-i]*ny[n-2] mod mo) mod mo;
kkk:=kkk*(bb[n-1]*aa[n-i] mod mo);
ans:=(ans+kkk) mod mo;
end;
for i:=2 to n do
begin
kkk:=z[i]*ycl[2*n-i-2] mod mo;
kkk:=kkk*(ny[n-i]*ny[n-2] mod mo) mod mo;
kkk:=kkk*(aa[n-1]*bb[n-i] mod mo);
ans:=(ans+kkk) mod mo;
end;
writeln(ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: