题解 P4705 【玩游戏】

这题是真的神仙啊...居然用的 stl 来卡常?

话说 998244353 真的可以一眼 NTT ?

noteskey

所以说只要推柿子就好了但是有的地方的推导根本就想不到...

我们令第 t 个答案为 \(ANS_t\over nm\) ,除去 nm 其实就是算期望时要除去的方案数

那么有:

\[\begin{aligned}{}ANS_t=&\sum_{i=1}^{n} \sum_{j=1}^m (a_i+b_j)^t \\=&\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{k=0}^{t} \begin{pmatrix} t\\k \end{pmatrix} a_i^{k}b_{j}^{t-k} \\=&\sum_{k=0}^{t} \begin{pmatrix} t\\k \end{pmatrix} \sum_{i=1}^{n}a_i^{k} \sum_{j=1}^{m} b_{j}^{t-k} \\=& \sum_{k=0}^{t} \begin{pmatrix} t\\k \end{pmatrix} \Big( \sum_{i=1}^{n}a_i^{k} \Big) \Big(\sum_{j=1}^{m} b_{j}^{t-k} \Big) \\=&\sum_{k=0}^{t} t! \Big({ \sum_{i=1}^{n}a_i^{k}\over k! } \Big) \Big( {\sum_{j=1}^{m} b_{j}^{t-k} \over (t-k)!} \Big) \end{aligned}\]

那么我们发现这个东西就是卷积的形式了,于是我们的任务就是快速算出后面两个表达式所对应的的多项式

我们设:

\[\begin{aligned} f(k)=\sum_{i=1}^n a_i ^{k} \\ g(k)=\sum_{i=1}^{m}b_{i}^{k} \end{aligned}\]

那么我们只要求出 \(f(1...t) ,g(1...t)\) 即可

但是求出来没有这么简单...

我们考虑先求出:

\[f_j(x)=\sum_{i=1}^{k}a_j^{i}\]

然后我们令:

\[F(x)= \sum_{i=1}^{n} f_{i}(x)\]

那么 \(F(x)\) 的第 k 项就表示了

\[\sum_{i=1}^{i} a_{i}^{k} x^k\]

即:

\[[x^{k}]F(x)=\sum_{i=1}^{i} a_{i}^{k}\]

那么我们现在发现要求出 \(f_{j=1...n}(x)\) ,但是没有什么高效的办法能解决这个问题

于是我们把 \(f_{j}(x)\) 中的上限 k 改掉,变成 \(\infty\) ,这样我们就能用生成函数来解决了:

\[f_{j}(x)={1\over 1- a_i x} \]

然后就是把这些 \(f_j(x)\) 加起来了:

\[F(x)={1\over 1-a_1x} +{1\over 1-a_2x} + ...+{1\over 1-a_nx}\]

最后就是怎么合并这些 \(f_j(x)\) 的问题了,我们发现:

\[ln(1-a_ix)'={-a_i\over 1-a_ix}\]

发现这个东西和我们要求的东西蛮像的,那么这里又有:

\[\begin{aligned}G(x)=&\sum_{i=1}^{n} ln(1-a_ix)' \\ F(x)=&-x·G(x)+n \end{aligned}\]

那么我们的任务就已经是求出 G(x) 了

\[G(x)=\sum_{i=1}^{n} ln(1-a_ix)'= ln(\prod_{i=1}^n (1-a_ix))'\]

然后我们就要在优秀的时间内求出\(\prod_{i=1}^n (1-a_ix)\) ,然后取个 Ln 再求个 Inv ,右移一位让最低项为 n , \(F(x)\) 就构造好了

至于对 b 数组也是同样的求法,两个要求的多项式求出来后,我们还要让两个多项式除去对应的阶乘,然后再去卷积

卷完积后也和最开始的式子一样,第 t 项乘上 t! ,然后别忘了我们还要除去 nm 才是最终的答案...

最后就是顺序输出就好了

code

这没救了的压行【雾

//by Judge
#include<bits/stdc++.h>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(Rg int i=(a),I=(b)-1;i>I;--i)
#define ll long long
using namespace std;
const int mod=998244353;
const int iG=332748118;
const int M=524288+3;
typedef int arr[M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int inc(int x,int y){return (x+y)%mod;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int dec(int x,int y){return (x-y+mod)%mod;}
inline int read(){ int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int CCF=-1,Z;
inline void Ot(){fwrite(sr,1,CCF+1,stdout),CCF=-1;}
inline void print(int x,char chr='\n'){
    if(CCF>1<<20)Ot();if(x<0)sr[++CCF]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++CCF]=z[Z],--Z);sr[++CCF]=chr;
} int n,m,t,qq,rev,d,limit;
arr a,b,f,g,fac,ifac,lg,r[20],D[21],G[2];
inline int qpow(Rg int x,Rg int p=mod-2,Rg int s=1){
    for(;p;p>>=1,x=mul(x,x)) if(p&1) s=mul(s,x); return s;
}
inline void prep(int n=262143){ for(limit=1;limit<=n;limit<<=1);
    fac[0]=fac[1]=1; fp(i,2,limit) fac[i]=mul(fac[i-1],i);
    fp(d,1,19){ lg[1<<d]=d; fp(i,0,(1<<d)-1)
        r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));
    }
    for(Rg int t=(mod-1)>>1,i=1,x,y;i<limit;i<<=1,t>>=1){
        x=qpow(3,t),y=qpow(iG,t),G[0][i]=G[1][i]=1;
        fp(k,1,i-1) G[1][i+k]=mul(G[1][i+k-1],x);
        fp(k,1,i-1) G[0][i+k]=mul(G[0][i+k-1],y);
    }
}
inline void init(int n){
    for(limit=1;limit<n;limit<<=1); d=lg[limit];
}
inline void NTT(int* a,int tp){
    fp(i,0,limit-1) if(i<r[d][i]) swap(a[i],a[r[d][i]]);
    for(Rg int mid=1,I=2;mid<limit;mid<<=1,I<<=1)
        for(Rg int j=0,x,y;j<limit;j+=I) fp(k,0,mid-1)
            x=a[j+k],y=mul(a[j+k+mid],G[tp][mid+k]),
            a[j+k]=inc(x,y),a[j+k+mid]=dec(x,y);
    if(tp) return ; int inv=qpow(limit);
    fp(i,0,limit-1) a[i]=mul(a[i],inv);
}
inline void Mul(int* a,int* b,int* c,int n){
    static arr A,B; fp(i,0,n-1) A[i]=a[i],B[i]=b[i];
    fill(A+n,A+limit,0),fill(B+n,B+limit,0),NTT(A,1),NTT(B,1);
    fp(i,0,limit-1) A[i]=mul(A[i],B[i]); NTT(A,0),copy(A,A+limit,c);
}
void Inv(int* a,int* b,int n){
    if(n==1) return b[0]=qpow(a[0]),void();
    Inv(a,b,n>>1),init(n<<1); static arr c,d;
    fp(i,0,n-1) c[i]=a[i],d[i]=b[i];
    fp(i,n,limit-1) c[i]=d[i]=0; NTT(c,1),NTT(d,1);
    fp(i,0,limit-1) c[i]=mul(c[i],mul(d[i],d[i])); NTT(c,0);
    fp(i,0,n-1) b[i]=dec(inc(b[i],b[i]),c[i]);
}
inline void Derv(int* a,int* b,int n){
    fp(i,1,n-1) b[i-1]=mul(a[i],i); b[n-1]=0;
}
inline void Ln(int* a,int* b,int n){ static arr c,d;
    memset(c,0,(n+1)<<2),memset(d,0,(n+1)<<2);
    Derv(a,c,n),Inv(a,d,n),init(n<<1);
    Mul(c,d,b,n),fill(b+n,b+limit,0);
}
inline void solv(int* a,int d,int l,int r){
    if(l==r) return D[d][0]=1,D[d][1]=mod-a[l],void(); static arr A,B;
    int mid=(l+r)>>1; solv(a,d,l,mid),solv(a,d+1,mid+1,r),init(r-l+2);
    fp(i,0,mid-l+1) A[i]=D[d][i]; fp(i,0,r-mid) B[i]=D[d+1][i];
    fill(A+mid-l+2,A+limit,0),fill(B+r-mid+1,B+limit,0);
    Mul(A,B,D[d],r-l+1),fill(D[d]+r-l+2,D[d]+limit,0);
}
int main(){ n=read(),m=read(),rev=qpow(mul(n,m)),prep();
    fp(i,1,n) a[i]=read(); fp(i,1,m) b[i]=read();
    solv(a,1,1,n),copy(D[1],D[1]+n+1,f);
    solv(b,1,1,m),copy(D[1],D[1]+m+1,g);
    t=read(),qq=max(max(n,m),t); init(qq+1),qq=limit;
    Ln(f,f+1,qq),Ln(g,g+1,qq),f[0]=n,g[0]=m;
    fp(i,1,qq-1) f[i]=dec(mod,f[i]),g[i]=dec(mod,g[i]);
    fac[0]=ifac[0]=ifac[1]=1; fp(i,1,qq-1) fac[i]=mul(fac[i-1],i);
    fp(i,2,qq-1) ifac[i]=mul(mod-mod/i,ifac[mod%i]);
    fp(i,1,qq-1) ifac[i]=mul(ifac[i],ifac[i-1]);
    fp(i,0,qq-1) f[i]=mul(f[i],ifac[i]),g[i]=mul(g[i],ifac[i]);
    fp(i,qq,qq<<1) f[i]=g[i]=0; init(qq<<1),NTT(f,1),NTT(g,1);
    fp(i,0,limit-1) f[i]=mul(f[i],g[i]); NTT(f,0);
    fp(i,1,t) print(mul(f[i],mul(fac[i],rev))); return Ot(),0;
}

猜你喜欢

转载自www.cnblogs.com/Judge/p/10748264.html