【NOI2017模拟4.5】数字格

题目

Description

菁菁堂有一块数字格,那是王解体最喜欢去的地方。
传说中,这条气势磅礴的数字格,有N行N列,每一个格子里均有一个数。
敢于挑战自己的王解体决定来挑战这道通过率为百分之九十九的题目。
格子的第一行及第一列均是给定的:
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)时,通过率将达到百分之百。

Input

题目包含多组测试数据,每组测试数据占3行。
对于每组测试数据:
第一行包含4个整数N,a,b,c。
第二行包含N个整数,表示l[1],…,l[N]
第三行包含N个整数,表示t[1],…,t[N]

Output

对于每组数据,输出一行,包含一个整数,表示王解体得到的答案。

Sample Input

3 0 0 0
0 0 2
0 3 0
4 3 5 2
7 1 4 3
7 4 4 8

Sample Output

0
41817

Data Constraint

10%的数据:N<=1000
30%的数据:N<=10000
100%的数据:N<=200000,a,b,c<=1000000,l[1]=t[1],1<=l[k],t[k]<=1000000

题解

我们首先考虑第一行和第一列中的数的a,b对于答案的贡献
设p(i,j)
可以发现就是 Cnini+nj ,那么a,b对于答案的贡献十分好求
然后我们考虑c对于答案的贡献,朴素的计算方法应该是 ni=2ni=2Cnini+njanibnjc
然后我们发现可以从终点开始快速的求出每一个斜率为 4/π 的线覆盖的点的贡献和
就是f[i]=(a+b)*f[i-1],这个手玩一下还是十分显然的
但是我们发现过了对角线之后这个东西开始超过了我们的区间,所以我们每次要减去最上面和最左边的那一个,可以发现这两个位置的第一步是固定的,所以不要被套路了
然后我们就可以在线性的时间内解决这一问题了(不包括快速幂的话)

贴代码

const md=1000003;
var
    l,t:array[0..200005]of int64;
    s,b1,a1:array[0..400005]of int64;
    i,j:longint;
    n,a,b,c,x,y,z,ans,tc:int64;
function quickmi(x,y:int64):int64;
var
    p,t:int64;
begin
    x:=x mod md;
    p:=1;
    while y>0 do
    begin
        if y mod 2=1 then p:=(p*x) mod md;
        x:=(x*x) mod md;
        y:=y div 2;
    end;
    exit(p);
end;
procedure work;
var
    pp:longint;
begin
    readln(n,a,b,c);
    s[0]:=1;
    for i:=1 to 2*n do s[i]:=(s[i-1]*i) mod md;
    a1[0]:=1;
    for i:=1 to n do a1[i]:=(a1[i-1]*a) mod md;
    b1[0]:=1;
    for i:=1 to n do b1[i]:=(b1[i-1]*b) mod md;
    a1[n+1]:=quickmi(b,n);
    for i:=1 to n do
    begin
        read(pp);
        if i=1 then continue;
        x:=(quickmi(s[n-2]*s[n-i],md-2)*s[2*n-i-2]) mod md;
        l[i]:=x;
        y:=(b1[n-i]*a1[n-1]) mod md;
        //y:=(quickmi(b,n-i)*quickmi(a,n-1)) mod md;
        x:=(x*y) mod md;
        x:=(x*pp) mod md;
        ans:=(ans+x) mod md;
    end;
    readln;
    for i:=1 to n do
    begin
        read(pp);
        if i=1 then continue;
        x:=l[i];
        y:=(b1[n-1]*a1[n-i]) mod md;
        //y:=(quickmi(b,n-1)*quickmi(a,n-i)) mod md;
        x:=(x*y) mod md;
        x:=(x*pp) mod md;
        ans:=(ans+x) mod md;
    end;
    readln;
    z:=1;
    for i:=1 to n-2 do
    begin
        z:=(z*(a+b)) mod md;
        ans:=(ans+z*c) mod md;
    end;
    for i:=0 to n-3 do
    begin
        z:=(z*(a+b)) mod md;
        x:=(quickmi(s[n-2]*s[i],md-2)*s[n-2+i]) mod md;
        y:=(a1[i]*b1[n-1]);
        y:=y+(a1[n-1]*b1[i]) mod md;
        y:=(y*x) mod md;
        z:=(z+md-y) mod md;
        ans:=(ans+c*z) mod md;
    end;
    ans:=(ans+c) mod md;
    writeln(ans);
end;
begin
    assign(input,'matrix.in'); reset(input);
    assign(output,'matrix.out'); rewrite(output);
    while not eof do
    begin
        ans:=0;
        work;
    end;
    close(input); close(output);
end.

你可能感兴趣的:(数学)