斯特林数和下降幂

P5395 第二类斯特林数·行

给定\(n\),对于所有的整数 \(i\in[0,n]\),你要求出 \({n\brace i}\)\(n\le 2\times 10^5\)

做法是 NTT 卷积

\[{n\brace m}=\sum_{i=0}^m \frac{i^n}{i!}\frac{(-1)^{m-i}}{(m-i)!} \]

如果你不知道哪里有卷积:

\[\begin{aligned} \\H(x)&=F(x)G(x) \\H(x)&=\sum_{i=0}^n{n\brace i}x^i \\F(x)&=\sum_{i=0}^n\frac{i^n}{i!}x^i \\G(x)&=\sum_{i=0}^n\frac{(-1)^i}{i!}x^i \end{aligned} \]

点击查看代码
/*
* Author: ShaoJia
* Last Modified time: 2022-10-06 21:42:02
* Motto: We'll be counting stars.
*/
// #pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define debug(...) cerr<<"#"<<__LINE__<<": "<<__VA_ARGS__<<endl
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define Rof(i,j,k) for(int i=(j),i##_=(k);i>=i##_;i--)
#define lob lower_bound
#define upb upper_bound
#define fir first
#define sec second
#define mkp make_pair
#define siz(x) ((int)(x).size())
#define pb emplace_back
#define ckmx(a,b) a=max(a,b)
#define ckmn(a,b) a=min(a,b)
#define ll long long
#define pi pair<int,int>
const int N=1<<19;
const ll mod=167772161;
ll pw(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1){
			(res*=x)%=mod;
		}
		y>>=1;
		(x*=x)%=mod;
	}
	return res;
}
ll f[N],ivf[N],F[N],G[N],st[N],w[N];
int n,lim,B=0,tax[N];
void mktw(){
	tax[0]=0;
	For(i,1,lim-1) tax[i]=(tax[i>>1]>>1)|((i&1)<<(B-1));
	ll wn=pw(3,(mod-1)/lim);
	w[0]=1;
	For(i,1,lim-1) w[i]=w[i-1]*wn%mod;
}
void DFT(ll *a){
	For(i,0,lim-1) if(i<tax[i]) swap(a[i],a[tax[i]]);
	ll x,y;
	for(int len=2;len<=lim;len<<=1){
		for(int i=0;i<lim;i+=len){
			For(j,0,(len>>1)-1){
				x=a[i+j];
				y=a[i+j+(len>>1)]*w[lim/len*j]%mod;
				a[i+j]=(x+y)%mod;
				a[i+j+(len>>1)]=(x-y+mod)%mod;
			}
		}
	}
}
void IDFT(ll *a){
	ll x=pw(lim,mod-2);
	reverse(a+1,a+lim);
	DFT(a);
	For(i,0,lim-1) (a[i]*=x)%=mod;
}
signed main(){ios::sync_with_stdio(false),cin.tie(nullptr);
	cin>>n;
	f[0]=1; For(i,1,n) f[i]=f[i-1]*i%mod;
	ivf[n]=pw(f[n],mod-2); Rof(i,n,1) ivf[i-1]=ivf[i]*i%mod;
	For(i,0,n) F[i]=pw(i,n)*ivf[i]%mod;
	For(i,0,n) G[i]=(i&1?mod-1:1)*ivf[i]%mod;
	while((1<<B)<=2*n) B++;
	lim=1<<B;
	mktw(),DFT(F),DFT(G);
	For(i,0,lim-1) st[i]=F[i]*G[i]%mod;
	IDFT(st);
	For(i,0,n) cout<<st[i]<<" "; cout<<"\n";
return 0;}

P2791 幼儿园篮球题

只因你太美

我们要求的是

\[\frac{\sum_{i=0}^ki^L\binom{m}{i}\binom{n-m}{k-i}}{\binom{n}{k}} \]

分母平凡,算分子,发现 \(i^L\) 难搞,直接下降幂

\[\begin{aligned} &\sum_{i=0}^ki^L\binom{m}{i}\binom{n-m}{k-i} \\=&\sum_{i=0}^k\binom{m}{i}\binom{n-m}{k-i}\sum_{j=0}^i\binom{i}{j}j!{L\brace j} \\=&\sum_{j=0}^kj!{L\brace j}\sum_{i=j}^k\binom{i}{j}\binom{m}{i}\binom{n-m}{k-i} \\=&\sum_{j=0}^kj!{L\brace j}\binom{m}{j}\sum_{i=j}^k\binom{m-j}{i-j}\binom{n-m}{k-i} \\=&\sum_{j=0}^kj!{L\brace j}\binom{m}{j}\sum_{i=0}^{k-j}\binom{m-j}{i}\binom{n-m}{k-i-j} \\=&\sum_{j=0}^kj!{L\brace j}\binom{m}{j}\binom{n-j}{k-j} \end{aligned} \]

NTT 卷积 \(O(L\log L)\) 求出 \(\forall x\in[0,L]\cap\mathbb{Z},{L\brace x}\)

我们发现最后的式子其实是

\[\sum_{i=0}^{\min(k,m,L)}i!{L\brace i}\binom{m}{i}\binom{n-i}{k-i} \]

最终复杂度 \(O(L\log L+SL)\)\(S\) 是数据组数),略卡空间。

点击查看代码
/*
* Author: ShaoJia
* Last Modified time: 2022-10-06 21:12:45
* Motto: We'll be counting stars.
*/
// #pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define debug(...) cerr<<"#"<<__LINE__<<": "<<__VA_ARGS__<<endl
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define Rof(i,j,k) for(int i=(j),i##_=(k);i>=i##_;i--)
#define lob lower_bound
#define upb upper_bound
#define fir first
#define sec second
#define mkp make_pair
#define siz(x) ((int)(x).size())
#define pb emplace_back
#define ckmx(a,b) a=max(a,b)
#define ckmn(a,b) a=min(a,b)
#define ll long long
#define pi pair<int,int>
const ll mod=998244353;
const int N=1<<19,V=20000001;
ll pw(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1){
			(res*=x)%=mod;
		}
		y>>=1;
		(x*=x)%=mod;
	}
	return res;
}
int n,m,k,L,B,lim,tax[N],f[V],ivf[V];//f & ivf longlong MLE
ll F[N],G[N],st[N],w[N];
void mktw(){
	tax[0]=0;
	For(i,1,lim-1) tax[i]=(tax[i>>1]>>1)|((i&1)<<(B-1));
	ll wn=pw(3,(mod-1)/lim);
	w[0]=1;
	For(i,1,lim-1) w[i]=w[i-1]*wn%mod;
}
void DFT(ll *a){
	For(i,0,lim-1) if(i<tax[i]) swap(a[i],a[tax[i]]);
	ll x,y;
	for(int len=2;len<=lim;len<<=1){
		for(int i=0;i<lim;i+=len){
			For(j,0,(len>>1)-1){
				x=a[i+j];
				y=a[i+j+(len>>1)]*w[lim/len*j]%mod;
				a[i+j]=(x+y)%mod;
				a[i+j+(len>>1)]=(x-y+mod)%mod;
			}
		}
	}
}
void IDFT(ll *a){
	ll x=pw(lim,mod-2);
	reverse(a+1,a+lim);
	DFT(a);
	For(i,0,lim-1) (a[i]*=x)%=mod;
}
void init(){
	f[0]=1;
	For(i,1,V-1) f[i]=1ll*f[i-1]*i%mod;
	ivf[V-1]=pw(f[V-1],mod-2);
	Rof(i,V-1,1) ivf[i-1]=1ll*ivf[i]*i%mod;
	For(i,0,L) F[i]=pw(i,L)*ivf[i]%mod;
	For(i,0,L) G[i]=(i&1?mod-1:1ll)*ivf[i]%mod;
	B=0;
	while((1<<B)<=2*L) B++;
	lim=1<<B;
	mktw();
	DFT(F);
	DFT(G);
	For(i,0,lim-1) st[i]=F[i]*G[i]%mod;
	IDFT(st);
	// For(i,0,L) cout<<st[i]<<"*"; cout<<"\n";
}
ll C(ll x,ll y){ return 1ll*f[x]*ivf[y]%mod*ivf[x-y]%mod; }
ll iC(ll x,ll y){ return 1ll*ivf[x]*f[y]%mod*f[x-y]%mod; }
void work(){
	cin>>n>>m>>k;
	int tot=min({k,m,L});
	ll ans=0;
	For(i,0,tot) (ans+=f[i]*st[i]%mod*C(m,i)%mod*C(n-i,k-i))%=mod;
	cout<<ans*iC(n,k)%mod<<"\n";
}
signed main(){ios::sync_with_stdio(false),cin.tie(nullptr);
	int T;cin>>n>>m>>T>>L;
	init();while(T--)work();
return 0;}

CF1528F AmShZ Farm

后面部分就是 第二类斯特林数·行,前面部分见 2023sol2。

posted @ 2022-08-07 20:44  ShaoJia  阅读(30)  评论(0编辑  收藏  举报