「PKUWC2018」猎人杀

https://loj.ac/problem/2541

题解

考虑容斥,令集合S为我们钦定S集合必须要在1号节点后面,那么答案为。

\[ans=\sum_{S}(-1)^{|S|}P(S) \]

然后这个\(P(S)\)\(\frac{w_1}{w_1+w_S}\)

这个需要想一想,或者我们考虑一个事情,就是每次死一个人概率的分母不会变,所以我们可以把它补成一样的,就是这个人死后有可能还会被选上,如果选上的话就再选一次,列出式子就是:

\[\sum_{i=0}^{\infty}(1-\frac{w_s+w_1}{sum})\frac{w_1}{sum} \]

\[\frac{w_1}{w_1+w_s} \]

所以我们要求所有的\(w_s\)

我们令生成函数\(G=\sum_{i=0}^{\infty}x^i\)表示w的和为i的\(sum\)的系数和,因为总和题目有保证,所以就可以分治\(FFT\)了。

代码

#include<bits/stdc++.h>
#define N 270002
using namespace std;
typedef long long ll;
const int mod=998244353;
const int G=3;
const int Gi=332748118;
ll a[42][N];
int rev[N],w[N],cnt[N],n;
int tot,rbs[N];
inline ll rd(){
  ll x=0;char c=getchar();bool f=0;
  while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  return f?-x:x;
}
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline ll power(ll x,ll y){
  ll ans=1;
  while(y){if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;}
  return ans;
}
inline void NTT(ll *a,int l,int tag){
  for(int i=1;i<l;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
  for(int i=1;i<l;i<<=1){
    ll wn=power(tag==1?G:Gi,(mod-1)/(i<<1));
    for(int j=0;j<l;j+=(i<<1)){
      ll w=1;
      for(int k=0;k<i;++k,w=w*wn%mod){
        ll x=a[j+k],y=a[i+j+k]*w%mod;
        MOD(a[j+k]=x+y);MOD(a[i+j+k]=x-y+mod);
      }
    }
  }
  if(tag<0){
    ll ny=power(l,mod-2);
    for(int i=0;i<l;++i)a[i]=a[i]*ny%mod;
  }
}
void solve(int now,int L,int R){
  if(L==R){
     cnt[now]=w[L];
     a[now][0]=1;a[now][w[L]]=mod-1;
     return;
  }
  int mid=(L+R)>>1;
  int x=rbs[0]?rbs[rbs[0]--]:++tot,y=rbs[0]?rbs[rbs[0]--]:++tot;
  solve(x,L,mid);solve(y,mid+1,R);
  cnt[now]=cnt[x]+cnt[y];
  int l=1,num=0;
  while(l<=(cnt[now]))l<<=1,num++;
  for(int i=1;i<l;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(num-1));
  NTT(a[x],l,1);NTT(a[y],l,1);
  for(int i=0;i<l;++i)a[now][i]=a[x][i]*a[y][i]%mod;
  NTT(a[now],l,-1);
  for(int i=0;i<l;++i)a[x][i]=0,a[y][i]=0;
  rbs[++rbs[0]]=x;rbs[++rbs[0]]=y;
}
int main(){
  n=rd();
  int sum=0;
  for(int i=1;i<=n;++i)w[i]=rd(),sum+=w[i];
  solve(0,2,n);
  ll ans=0;
  for(int i=0;i<=sum;++i){
    MOD(ans+=a[0][i]*power(w[1]+i,mod-2)%mod);
  }
  ans=ans*w[1]%mod;
  cout<<ans<<endl;
  return 0;
}
posted @ 2019-05-29 08:54  comld  阅读(136)  评论(0编辑  收藏  举报