【集训队作业2018】矩形

tag:推柿子


时间黑洞

又到了最喜欢毒瘤的推柿子题

首先dp式子很容易

\[f(i,j)=\begin{cases}p(f(i-1,j)+\alpha)+q(f(i,j-1)+\beta)&&i\geq1,j\geq1\\a_i&&i\geq1,j=0\\b_i&&i=0,j\geq1\\0&&i=j=0\end{cases} \]

显然\(p\alpha+q\beta\)这部分可以提出来单独计算,然后可以枚举每一个\(a_i,b_i\),直接计算它们对答案的贡献(a和b的计算类似)

Case 1

考虑\(b_i\)的贡献,先提出\(b_ih^i\),设\(A=ph^{n+1},B=qh\),则贡献类似于

\[\begin{bmatrix}1\\A&AB&AB^2\\A^2&2A^2B&3A^2B^2\\A^3&3A^3B&6A^3B^2\end{bmatrix} \]

\(ans=b_xh^xA\cdot\sum_{i=0}^{n-1}\sum_{j=0}^{n-x}A^iB^j\binom{i+j}i\),设后面一堆为\(f(x)\)

\[f(x)=\sum_{j=0}^{n-x}B^j\sum_{i=0}^{n-1}A^i\binom{i+j}i \]

然后继续设后面一堆为\(g(j)\),则\(f(n)=f(n-1)+B^ng(n)\)

\[g(n)=\sum_{i=0}^{k-1}A^i\binom{i+n}i(\text{避免混淆,这里把n写成了k}) \]

然后好像推不动了,式子里面看上去能动的就只有组合数了,把它拆开

\[g(n)=\sum_{i=0}^{k-1}A^i(\binom{(i-1)+n}{(i-1)}+\binom{i+n-1}i{}) \]

然后\(i=0\)时左边那个式子是无意义的,所以\(i\in[1,k-1]\),再代换一下令\(i'=i-1\)

\[g(n)=\sum_{i=0}^{k-2}A^{i+1}\binom{i+n}i+\sum_{i=0}^{k-1}A^i\binom{i+n-1}i \]

容易发现右边是\(g(n-1)\),右边是\(g(n)-(i=k-1)\)的那项

\[g(n)=g(n-1)+A(g(n)-\binom{n+k-1}{k-1}A^{k-1}) \]

然后对\(A=1\)分类讨论一下即可求出\(g\),然后推出\(f\)\(a_i\)的话其实把\(A\)\(B\)swap一下重新跑一遍就好,然后注意提出来的是\(a_xh^{x(n+1)}\)

Case 2

\(c=p\alpha+q\beta\),考虑\(c\)的贡献

枚举一个格子,再枚举它左上角的一个格子,这两个格子之间的每条路径都会产生\(cp^iq^j\)的贡献(\(ij\)\(xy\)坐标之差)

\[ans=\sum_{x=1}^nh^{x(n+1)}\sum_{y=1}^nh^y\sum_{i=0}^{x-1}\sum_{j=0}^{y-1}p^iq^j\binom{i+j}j \]

\(h^y\)后面一堆为\(G(x,y)\)

\[G(x,y)=h^y\sum_{i=0}^{x-1}\sum_{j=0}^{y-1}p^iq^j\binom{i+j}j \]

老套路把组合数拆了

\[G(x,y)=h^y\sum_{i=0}^{x-1}\sum_{j=0}^{y-1}p^iq^i(\binom{i+(j-1)}{(j-1)}+\binom{(i-1)+j}j) \]

第一个式子在\(j=0\)时无意义,第二个在\(i=0\)时无意义,但是这样会忽略掉\(i=j=0\)的情况,所以单独加上

\[G(x,y)=h^yq\sum_{i=0}^{x-1}\sum_{j=0}^{y-2}p^iq^j\binom{i+j}j+h^yp\sum_{i=0}^{x-2}\sum_{j=0}^{y-1}p^iq^j\binom{i+j}j+h^y \]

注意到右边是\(pG(x-1,y)\),左边是\(qG(x,y)减去j=y-1\)的情况

\[G(x,y)=pG(x-1,y)+q(G(x,y)-\sum_{i=0}^{x-1}p^iq^{y-1}h^y\binom{i+y-1}{y-1})+h^y \]

考虑我们要求的实际上是\(\sum_{x,y}G(x,y)\),所以设\(T(x)=\sum_{i=1}^nG(x,i)\)

\[T(x)=pT(x-1)+q(T(x)-\sum_{i=0}^{x-1}p^i\sum_{j=1}^nq^{j-1}h^j\binom{i+j-1}{j-1})+\sum_{i=1}^nh^i \]

中间那个式子换一下下标

\[\sum_{i=0}^{x-1}p^i\sum_{j=0}^{n-1}q^jh^{j+1}\binom{i+j}j \]

然后发现,它(右边部分提一个\(h\))居然长得和\(g(i)\)一样!
所以令\(A=qh\)求一遍\(g\)即可(实际上就是求\(a_i\)的时候的\(g\)

\[T(x)=pT(x-1)+q(T(x)-h\sum_{i=0}^{x-1}p^ig(i))+\sum_{i=1}^nh^y \]

\(q=1\)分类讨论一下可以求出\(T\)

(上述所有带和式的都可以前缀和优化)

于是复杂度\(O(n)\)(可能多一个快速幂的复杂度)


#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
    char ch; bool flag=false;
    while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
    for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
    if(flag)n=-n;
}

typedef long long ll;
const int MAXN = 200005;
const int MOD = 998244353;

inline int inc(int a, int b){
    a += b;
    if(a>=MOD) a -= MOD;
    return a;
}

inline int dec(int a, int b){
    a -= b;
    if(a<0) a += MOD;
    return a;
}

inline int ksm(int base, ll k=MOD-2){
    int res=1;
    while(k){
        if(k&1)
            res = 1ll*res*base%MOD;
        base = 1ll*base*base%MOD;
        k >>= 1;
    }
    return res;
}

int jc[MAXN<<1], invjc[MAXN<<1];
inline int C(int n, int m){return 1ll*jc[n]*invjc[m]%MOD*invjc[n-m]%MOD;}

int a[MAXN], b[MAXN], alpha, beta, n, h, p, q;
int S1[MAXN], S2[MAXN], ans, A, B;

int f[MAXN], g[MAXN], sg[MAXN], T[MAXN];

int main(){
    // freopen("dream2.in","r",stdin);
    Read(n); Read(h); Read(alpha); Read(beta);
    jc[0] = 1; for(register int i=1; i<=(n<<1); i++) jc[i] = 1ll*jc[i-1]*i%MOD;
    invjc[n<<1] = ksm(jc[n<<1]); for(register int i=(n<<1); i; i--) invjc[i-1] = 1ll*invjc[i]*i%MOD;
    int tmp; Read(p); Read(tmp); p = 1ll*p*ksm(tmp)%MOD;
    Read(q); Read(tmp); q = 1ll*q*ksm(tmp)%MOD;
    for(register int i=1; i<=n; i++) Read(a[i]);
    for(register int i=1; i<=n; i++) Read(b[i]);

    // bi的贡献
    for(register int i=1; i<=n; i++) ans = (ans+1ll*b[i]*ksm(h,i))%MOD;
    A = 1ll*p*ksm(h,n+1)%MOD; B = 1ll*q*h%MOD;
    if(A==1) for(register int i=0; i<n; i++) g[i] = C(n+i,n-1);
    else{
        for(register int i=0; i<n; i++) g[0] = inc(g[0],ksm(A,i));
        for(register int i=1; i<n; i++) g[i] = 1ll*dec(g[i-1],1ll*C(i+n-1,n-1)*ksm(A,n)%MOD)*ksm(dec(1,A))%MOD;
    }
    f[0] = g[0]; for(register int i=1; i<n; i++) f[i] = (f[i-1]+1ll*ksm(B,i)*g[i])%MOD;
    for(register int i=1; i<=n; i++) ans = (ans+1ll*b[i]*ksm(h,i)%MOD*A%MOD*f[n-i])%MOD;

    // ai的贡献
    for(register int i=1; i<=n; i++) ans = (ans+1ll*a[i]*ksm(h,1ll*i*(n+1)))%MOD;
    swap(A,B); memset(g,0,sizeof g);
    if(A==1) for(register int i=0; i<n; i++) g[i] = C(n+i,n-1);
    else{
        for(register int i=0; i<n; i++) g[0] = inc(g[0],ksm(A,i));
        for(register int i=1; i<n; i++) g[i] = 1ll*dec(g[i-1],1ll*C(i+n-1,n-1)*ksm(A,n)%MOD)*ksm(dec(1,A))%MOD;
    }
    f[0] = g[0]; for(register int i=1; i<n; i++) f[i] = (f[i-1]+1ll*ksm(B,i)*g[i])%MOD;
    for(register int i=1; i<=n; i++) ans = (ans+1ll*a[i]*ksm(h,1ll*i*(n+1))%MOD*A%MOD*f[n-i])%MOD;
    
    // c的贡献
    int c = (1ll*alpha*p+1ll*beta*q)%MOD;
    int spow=0; for(register int i=1, pw=h; i<=n; i++, pw=1ll*pw*h%MOD) spow = inc(spow,pw);
    if(q==1) for(register int i=1; i<=n; i++) T[i] = (1ll*p*T[i-1]+spow)%MOD;
    else{
        sg[0] = g[0]; 
        for(register int i=1; i<=n; i++) 
            sg[i] = (sg[i-1]+1ll*ksm(p,i)*g[i])%MOD,
            T[i] = 1ll*ksm(dec(1,q))*((1ll*p*T[i-1]%MOD-1ll*q*h%MOD*sg[i-1]%MOD+spow+MOD)%MOD)%MOD;
    }
    for(register int i=1; i<=n; i++) ans = (ans+1ll*c*T[i]%MOD*ksm(h,1ll*i*(n+1)))%MOD;

    cout<<ans<<endl;
    return 0;
}
posted @ 2021-07-01 15:17  oisdoaiu  阅读(84)  评论(0编辑  收藏  举报