感觉哪里不好下手?
猎人死了的话,$\sum w_i$会变。
怎么办呢?嗯,那么死了的猎人不下场,选到死了的猎人,就重新选一次。

现在 1 号猎人是最后一个死的,也就是我们要除掉别的猎人在 1 号之后死的情况。假设有几个猎人在 1 号之后死,他们的权值和为 $S$,那么这种情况的概率就是:

$$f(S)=\sum^{inf} (1-\frac{w_1+S}{\sum w})\frac{w_1}{\sum w}$$
(当然了,这种计算方法下,可能还是有除了权值和为 $S$的那些猎人以外的猎人在 1 后面死也被算进去了,所以要容斥)

我们现在容斥一下,首先取 $S=0$,然后减去至少一个猎人在 1 后死的,加上至少两个的,减去至少三个的……
可以发现构造一个生成函数 $\sum_{i=2}^n(1-x^{w_i})$,设 $x^i$的系数为 $a_i$,那么答案就是 $\sum a_i f(i)$
设 $W$是 $w_i$中的最大值。用分治 NTT 计算该生成函数,复杂度是 $O(WlogWlogn)$

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
    int q=0;char ch=' ';
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
    return q;
}
const int mod=998244353,N=262150,G=3;
int n,ans,w[N],A[20][N],rev[N],sz[20];
int qm(int x) {return x>=mod?x-mod:x;}
int ksm(int x,int y) {
    int re=1;
    for(;y;y>>=1,x=1LL*x*x%mod) if(y&1) re=1LL*re*x%mod;
    return re;
}
void NTT(int *a,int n,int x) {
    for(RI i=1;i<n;++i) if(rev[i]>i) swap(a[i],a[rev[i]]);
    for(RI i=1;i<n;i<<=1) {
        int gn=ksm(G,(mod-1)/(i<<1));
        for(RI j=0;j<n;j+=(i<<1)) {
            int g=1,t1,t2;
            for(RI k=0;k<i;++k,g=1LL*g*gn%mod) {
                t1=a[j+k],t2=1LL*g*a[j+i+k]%mod;
                a[j+k]=qm(t1+t2),a[j+i+k]=qm(t1-t2+mod);
            }
        }
    }
    if(x==1) return;
    int inv=ksm(n,mod-2);reverse(a+1,a+n);
    for(RI i=0;i<n;++i) a[i]=1LL*a[i]*inv%mod;
}
void getrev(int n,int len)
    {for(RI i=0;i<n;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));}
void work(int l,int r,int d) {
    if(l==r) {
        sz[d]=w[l];
        for(RI i=0;i<=sz[d];++i) A[d][i]=0;
        A[d][0]=1,A[d][w[l]]=mod-1;return;
    }
    int mid=(l+r)>>1,kn=1,len=0;
    work(l,mid,d),work(mid+1,r,d+1);
    sz[d]+=sz[d+1];while(kn<=sz[d]) kn<<=1,++len;
    getrev(kn,len);
    for(RI i=sz[d]-sz[d+1]+1;i<kn;++i) A[d][i]=0;
    for(RI i=sz[d+1]+1;i<kn;++i) A[d+1][i]=0;
    NTT(A[d],kn,1),NTT(A[d+1],kn,1);
    for(RI i=0;i<kn;++i) A[d][i]=1LL*A[d][i]*A[d+1][i]%mod;
    NTT(A[d],kn,-1);
}
int main()
{
    n=read();
    for(RI i=1;i<=n;++i) w[i]=read();
    if(n==1) {puts("1");return 0;}
    work(2,n,0);
    for(RI i=0;i<=sz[0];++i)
        ans=qm(ans+1LL*A[0][i]*w[1]%mod*ksm(qm(i+w[1]),mod-2)%mod);
    printf("%d\n",ans);
    return 0;
}
分类: 文章

litble

苟...苟活者在淡红的血色中,会依稀看见微茫的希望

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注