感觉求这个玩意的方法略迷,记录一下这个清奇的思路。
考虑展开 ( 1 + x ) t (1+x)^t (1+x)t
( 1 + x ) t = ∑ i = 0 ∞ ( t i ) x i = ∑ i = 0 ∞ x i t i ‾ i ! = ∑ i = 0 ∞ x i i ! ∑ j = 0 i [ i j ] ( − 1 ) i − j t j = ∑ j = 0 ∞ t j ∑ i = j ∞ x i i ! [ i j ] ( − 1 ) i − j \begin{aligned} (1+x)^t&=&&\sum_{i=0}^\infty {t\choose i}x^i\\ &=&&\sum_{i=0}^\infty \frac{x^it^{\underline{i}}}{i!}\\ &=&&\sum_{i=0}^\infty \frac{x^i}{i!}\sum_{j=0}^i\begin{bmatrix}i\\j\end{bmatrix}(-1)^{i-j}t^j\\ &=&&\sum_{j=0}^\infty t^j\sum_{i=j}^\infty\frac{x^i}{i!}\begin{bmatrix}i\\j\end{bmatrix}(-1)^{i-j} \end{aligned} (1+x)t====i=0∑∞(it)xii=0∑∞i!xitii=0∑∞i!xij=0∑i[ij](−1)i−jtjj=0∑∞tji=j∑∞i!xi[ij](−1)i−j
然后考虑 ln + exp \ln+\exp ln+exp的展开方式。
( 1 + x ) t = exp ( t ⋅ ln ( 1 + x ) ) = ∑ i = 0 ∞ t i ⋅ ( ln ( 1 + x ) ) i i ! \begin{aligned} (1+x)^t&=&&\exp(t\cdot \ln(1+x))\\ &=&&\sum_{i=0}^\infty t^i\cdot \frac{(\ln(1+x))^i}{i!} \end{aligned} (1+x)t==exp(t⋅ln(1+x))i=0∑∞ti⋅i!(ln(1+x))i
前后对比可以得到: ∑ j = i ∞ ( − 1 ) j − i [ j i ] x j i ! = ( ln ( 1 + x ) ) i i ! \sum_{j=i}^\infty \frac{(-1)^{j-i}\begin{bmatrix}j\\i\end{bmatrix}x^j}{i!}=\frac{(\ln(1+x))^i}{i!} j=i∑∞i!(−1)j−i[ji]xj=i!(ln(1+x))i
这是一种方法。
然而,我们考虑只有一个循环的置换的EGF:
∑ i = 1 ∞ ( i − 1 ) ! x i i ! = ∑ i = 1 ∞ x i i \sum_{i=1}^{\infty}\frac{(i-1)!x^i}{i!}=\sum_{i=1}^\infty\frac{x^i}{i} i=1∑∞i!(i−1)!xi=i=1∑∞ixi
直接对上面这个东西算K次方就能得到K个环的置换的生成函数。去掉环的排列顺序算上点的排列顺序就行了。
需要比较通用的快速幂板子。
时间复杂度 O ( n log n ) O(n\log n) O(nlogn)
代码:
#include
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=167772161;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
inline void Inc(int &a,int b){(a+=b)>=mod?a-=mod:0;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline void Mul(int &a,int b){a=mul(a,b);}
typedef std::vector<int> Poly;
std::ostream &operator<<(std::ostream &out,cs Poly &a){
if(!a.size())out<<"empty ";
else for(int re i:a)out<<i<<" ";
return out;
}
cs int bit=20,SIZE=1<<20|1;
int r[SIZE],*w[bit+1];
int fac[SIZE],ifac[SIZE],inv[SIZE];
inline void init_NTT(){
for(int re i=1;i<=bit;++i)w[i]=new int[1<<i-1];
int wn=power(3,mod-1>>bit);w[bit][0]=1;
for(int re i=1;i<(1<<bit-1);++i)w[bit][i]=mul(w[bit][i-1],wn);
for(int re i=bit-1;i;--i)
for(int re j=0;j<(1<<i-1);++j)w[i][j]=w[i+1][j<<1];
fac[0]=ifac[0]=fac[1]=inv[0]=inv[1]=1;
for(int re i=2;i<SIZE;++i)fac[i]=mul(fac[i-1],i),inv[i]=mul(inv[mod%i],mod-mod/i);
ifac[SIZE-1]=power(fac[SIZE-1],mod-2);
for(int re i=SIZE-2;i;--i)ifac[i]=mul(ifac[i+1],i+1);
}
inline void NTT(Poly &A,int len,int typ){
for(int re i=0;i<len;++i)if(i<r[i])std::swap(A[i],A[r[i]]);
for(int re i=1,d=1;i<len;i<<=1,++d)
for(int re j=0;j<len;j+=i<<1)
for(int re k=0;k<i;++k){
int &t1=A[j+k],&t2=A[j+k+i],t=mul(t2,w[d][k]);
t2=dec(t1,t),Inc(t1,t);
}
if(typ==-1){
std::reverse(A.begin()+1,A.begin()+len);
for(int re i=0,inv=power(len,mod-2);i<len;++i)Mul(A[i],inv);
}
}
inline void init_rev(int l){
for(int re i=0;i<l;++i)r[i]=r[i>>1]>>1|((i&1)?l>>1:0);
}
inline Poly operator*(Poly a,Poly b){
int deg=a.size()+b.size()-1,l=1;
while(l<=deg)l<<=1;init_rev(l);
a.resize(l),NTT(a,l,1);
b.resize(l),NTT(b,l,1);
for(int re i=0;i<l;++i)Mul(a[i],b[i]);
NTT(a,l,-1),a.resize(deg);
return a;
}
inline Poly Inv(cs Poly &a,int lim){
int n=a.size();Poly c,b(1,power(a[0],mod-2));
for(int re l=4;(l>>2)<lim;l<<=1){
init_rev(l);
c.resize(l>>1);for(int re i=0;i<(l>>1);++i)c[i]=i<n?a[i]:0;
c.resize(l),NTT(c,l,1);
b.resize(l),NTT(b,l,1);
for(int re i=0;i<l;++i)Mul(b[i],dec(2,mul(b[i],c[i])));
NTT(b,l,-1),b.resize(l>>1);
}b.resize(lim);
return b;
}
inline Poly Deriv(Poly a){
for(int re i=0;i+1<a.size();++i)a[i]=mul(a[i+1],i+1);
a.pop_back();return a;
}
inline Poly Integ(Poly a){a.push_back(0);
for(int re i=a.size()-1;i;--i)a[i]=mul(a[i-1],inv[i]);
a[0]=0;return a;
}
inline Poly Ln(Poly a,int lim){
a=Integ(Deriv(a)*Inv(a,lim));
a.resize(lim);
return a;
}
inline Poly Ln(cs Poly &a){return Ln(a,a.size());}
inline Poly Exp(cs Poly &a,int lim){
Poly c,b(1,1);int n=a.size();
for(int re l=2;(l>>1)<lim;l<<=1){
c=Ln(b,l);
for(int re i=0;i<l;++i)c[i]=dec(i<n?a[i]:0,c[i]);
Inc(c[0],1);
b=b*c;b.resize(l);
}b.resize(lim);
return b;
}
inline Poly Exp(cs Poly &a){return Exp(a,a.size());}
inline Poly Ksm(cs Poly &a,int t,int lim){
int bot=0,l=1;
while(bot<a.size()&&!a[bot])++bot;
if((ll)t*bot>lim)return Poly(lim,0);
while(l<lim)l<<=1;
Poly b(l,0);
for(int re i=bot;i<lim;++i)b[i-bot]=a[i];
int p=power(a[bot],mod-2);
for(int re i=0;i<l;++i)Mul(b[i],p);b=Ln(b,l);
for(int re i=0;i<l;++i)Mul(b[i],t);b=Exp(b);b.resize(lim);
p=power(a[bot],t);
for(int re i=0;i<lim;++i)Mul(b[i],p);
Poly ans;ans.resize(lim);
for(int re i=t*bot;i<lim;++i)ans[i]=b[i-t*bot];
return ans;
}
inline Poly Ksm(cs Poly &a,int k){return Ksm(a,k,a.size());}
Poly f;
signed main(){
#ifdef zxyoi
freopen("first_stirling_col.in","r",stdin);
freopen("first_stirling_col.out","w",stdout);
#endif
init_NTT();
int n,k;scanf("%d%d",&n,&k);
f.resize(n+1);
for(int re i=1;i<=n;++i)f[i]=inv[i];
f=Ksm(f,k);
for(int re i=0;i<=n;++i){
Mul(f[i],mul(ifac[k],fac[i]));
cout<<f[i]<<" ";
}
return 0;
}