(T)组询问,每次询问(n)个有标号的球随机放入任意个有标号的集合中,不能有空集的集合数量的期望。(n,Tleq 10^5)
期望转计数,答案就是所有情况的集合数之和/情况数。设(g_n)表示情况数,用有标号计数的经典转移:枚举第一个集合中有哪些球,得到
[egin{align}
g_n=sum_{i=1}^n{nchoose i}g_{n-i}=sum_{i=0}^n{nchoose i}g_{n-i}-g_n
\2g_n=sum_{i=0}^n{nchoose i}g_{n-i}(ngeq 1)
\g_0=1
end{align}
]
根据(g)的转移很显然能写出(g)的(EGF):
[egin{align}
2G(x)=e^xG(x)+1
\G(x)=frac{1}{2-e^x}
end{align}
]
多项式求逆就可以求出(G)了。
接下来设(f_n)表示所有情况的集合数之和。转移类似地有:
[egin{align}
\f_n=sum_{i=1}^n{nchoose i}(g_{n-i}+f_{n-i})=g_n+sum_{i=1}^n{nchoose i}f_{n-i}=g_n+sum_{i=0}^n{nchoose i}f_{n-i}-f_n
\2f_n=g_n+sum_{i=0}^n{nchoose i}f_{n-i}(ngeq 1)
\f_0=0
end{align}
]
还是写出(f)的(EGF):
[egin{align}
\2F(x)=G(x)+e^xF(x)-1
\(e^x-2)F(x)=1-G(x)=frac{1-e^x}{2-e^x}
\F(x)=frac{e^x-1}{(e^x-2)^2}
end{align}
]
仍然多项式求逆,最后(n)的答案就是(frac{[x^n]F(x)}{[x^n]G(x)})。复杂度(mathcal{O}(nlog n))。
#include<bits/stdc++.h>
#define rg register
#define il inline
#define cn const
#define gc getchar()
#define fp(i,a,b) for(rg int i=(a),ed=(b);i<=ed;++i)
#define fb(i,a,b) for(rg int i=(a),ed=(b);i>=ed;--i)
#define go(u) for(rg int i=head[u];~i;i=e[i].nxt)
using namespace std;
typedef cn int cint;
typedef long long LL;
il void rd(int &x){
x = 0;
rg int f(1); rg char c(gc);
while(c<'0'||'9'<c){if(c=='-')f=-1;c=gc;}
while('0'<=c&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc;
x*=f;
}
cint maxn = 100010, mod = 998244353, invG = (mod+1)/3;
int T, n, a[maxn], fac[maxn], ifac[maxn];
int A[maxn<<2], F[maxn<<2], G[maxn<<2], inv_ary[maxn<<2];
int lim, hst, rev[maxn<<2];
il int fpow(int a, int b, int ans = 1){
for(; b; b >>= 1, a = 1ll*a*a%mod)if(b&1)ans = 1ll*ans*a%mod;
return ans;
}
il void ntt(int *a, cint &typ){
fp(i, 0, lim-1)if(i > rev[i])swap(a[i], a[rev[i]]);
for(rg int md = 1; md < lim; md <<= 1){
rg int len = md<<1, Gn = fpow(typ ? invG : 3, (mod-1)/len);
for(rg int l = 0; l < lim; l += len){
for(rg int nw = 0, Pow = 1; nw < md; ++nw, Pow = 1ll*Pow*Gn%mod){
rg int x = a[l+nw], y = 1ll*a[l+nw+md]*Pow%mod;
a[l+nw] = (x+y)%mod, a[l+nw+md] = (x-y+mod)%mod;
}
}
}
if(!typ)return;
rg int inv = fpow(lim, mod-2);
fp(i, 0, lim-1)a[i] = 1ll*a[i]*inv%mod;
}
il void init(int n){
lim = 1, hst = 0;
while(lim < n)lim <<= 1, ++hst;
fp(i, 1, lim-1)rev[i] = (rev[i>>1]>>1)|((i&1)<<hst-1);
}
void get_inv(int *a, int *f, int n){
if(n == 1)return f[0] = fpow(a[0], mod-2), void();
get_inv(a, f, n+1>>1), init(n*2-1);
fp(i, 0, n-1)inv_ary[i] = a[i];
ntt(f, 0), ntt(inv_ary, 0);
fp(i, 0, lim-1)f[i] = 1ll*f[i]*(2-1ll*f[i]*inv_ary[i]%mod+mod)%mod;
ntt(f, 1);
fp(i, n, lim-1)f[i] = 0;
fp(i, 0, lim-1)inv_ary[i] = 0;
}
int main(){
rd(T);
fp(i, 1, T)rd(a[i]), n = max(n, a[i]);
fac[0] = 1; fp(i, 1, n)fac[i] = 1ll*fac[i-1]*i%mod;
ifac[n] = fpow(fac[n], mod-2); fb(i, n, 1)ifac[i-1] = 1ll*ifac[i]*i%mod;
fp(i, 0, n)A[i] = mod-ifac[i];
A[0] = (A[0]+2)%mod, get_inv(A, G, n+1);
init(n*2+1), ntt(A, 0);
fp(i, 0, lim-1)A[i] = 1ll*A[i]*A[i]%mod;
ntt(A, 1);
fp(i, n+1, lim-1)A[i] = 0;
get_inv(A, F, n+1);
fp(i, 1, n)A[i] = ifac[i];
A[0] = 0, init(n*2+1), ntt(A, 0), ntt(F, 0);
fp(i, 0, lim-1)F[i] = 1ll*F[i]*A[i]%mod;
ntt(F, 1);
fp(i, 1, T)printf("%lld
", 1ll*F[a[i]]*fpow(G[a[i]], mod-2)%mod);
return 0;
}