题意:场上有n个人 在某一时刻同时向周围随机的一个人开枪 概率相同 射中的概率为p 求场上活下来k个人的概率对998244353取余 k从0取到n
设 f(S)为死了的人的集合为S的概率 g(S)为死了的人的集合为S的子集的概率
f(x)为死了x人的概率 g(x)为死了的人的集合大小为x的概率
由容斥定理可得
对于所有大小相同的集合S而言 f(S)和g(S)的值相同
令S为某一种固定的集合 g(S)表示死的人均是S的元素的概率
对于在S内的人而言 他要么开枪没打中 要么开枪杀了除他自己以外的S内的人
对于在S外的人而言 他要么开枪没打中 要么开枪杀了S内的人
所以
可以将x-i看成j 那么i+j=x 卷积对应的系数
用NTT计算卷积 最后得到的为死了x人的概率
k=n-x
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
using namespace std;
const int MOD=998244353;
typedef long long ll;
ll a[1<<22],b[1<<22],rev[1<<22],fac[1<<22],ifac[1<<22],g[1<<22];
ll n,x,ans,M=1e6;
ll QP(ll x,ll n){//快速幂
ll res=1;
while(n){
if(n&1){
res=(res*x)%MOD;
}
x=(x*x)%MOD;
n>>=1;
}
return res;
}
void NTT(ll a[],int lim,int type)
{
for(int i=0;i<lim;i++)
if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int mid=1;mid<lim;mid<<=1)
{
ll wn=QP(3,(MOD-1)/(mid*2));
if(type==-1) wn=QP(wn,MOD-2);
for(int i=0,len=mid<<1;i<lim;i+=len)
{
ll w=1;
for(int j=0;j<mid;j++,w=w*wn%MOD)
{
ll x=a[i+j],y=w*a[i+j+mid]%MOD;
a[i+j]=(x+y)%MOD,a[i+j+mid]=(x-y+MOD)%MOD;
}
}
}
if(type==-1)
{
ll inv_=QP(lim,MOD-2);
for(int i=0;i<lim;i++)
a[i]=a[i]*inv_%MOD;
}
}
int main(){
ll n,pa,pb;
cin>>n>>pa>>pb;
ll p=pa*QP(pb,MOD-2)%MOD;
ll np=(1+MOD-p)%MOD,inv=QP(n-1,MOD-2);
fac[0]=1;
for(int i=1;i<=n;i++)fac[i]=(fac[i-1]*i)%MOD;
ifac[n]=QP(fac[n],MOD-2);
for(int i=n-1;i>=0;i--)ifac[i]=ifac[i+1]*(i+1)%MOD;
g[0]=QP((1+MOD-p)%MOD,n);
for(int i=1;i<=n;i++)
{
g[i]=QP((np+p*(i-1)%MOD*inv%MOD)%MOD,i)*QP((np+p*i%MOD*inv%MOD)%MOD,n-i)%MOD;
}
for(int i=0;i<=n;i++)
{
a[i]=g[i]*ifac[i]%MOD;
if(i%2)b[i]=MOD-ifac[i];
else b[i]=ifac[i];
}
ll len=21,lim=1<<21;
for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<len-1);
NTT(a,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;i++)a[i]=a[i]*b[i]%MOD;
NTT(a,lim,-1);
for(int i=0;i<=n;i++)
{
printf("%lld\n",fac[n]*ifac[i]%MOD*a[n-i]%MOD);
}
return 0;
}