斯特林数的计算方法

Posted shzr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了斯特林数的计算方法相关的知识,希望对你有一定的参考价值。

  做了一个斯特林数的题,发现需要快速求第一类斯特林数,感觉是时候学一下了。按照从简单到难的顺序来写吧。

 

第二类斯特林数·行

  给出n,求$egin{Bmatrix} n\0 end{Bmatrix}~,~egin{Bmatrix} n\1 end{Bmatrix}dotsegin{Bmatrix} n\n end{Bmatrix}$;$nleq 2 imes 10^5$

  $egin{Bmatrix} n\m end{Bmatrix}=frac{1}{m!}sumlimits_{i=0}^m(-1)^iinom{m}{i}(m-i)^n$

  $=frac{1}{m!}sumlimits_{i=0}^m(-1)^ifrac{m!}{i!(m-i)!}(m-i)^n$

  $=sumlimits_{i=0}^mfrac{(-1)^i(m-i)^n}{i!(m-i)!}$

  $=sumlimits_{i=0}^mfrac{(-1)^i}{i!} imes frac{(m-i)^n}{(m-i)!}$

  可以看得出,由于 (m-i)+i=m ,这就是一个卷积的形式了。我们把:$f(x)=sum frac{(-1)^i}{i!}x^i$ 和 $g(x)=sum frac{x^n}{x!}x^i$ 卷起来,得到的多项式的各项系数就是答案啦。

  技术图片
 1 # include <cstdio>
 2 # include <iostream>
 3 # define R register int
 4 
 5 using namespace std;
 6 
 7 const int N=600005;
 8 const int mod=167772161;
 9 const int inv_g=(mod+1)/3;
10 int n,f[N],g[N],len,rev[N];
11 int inv[N],fac[N];
12 
13 int add (int a,int b)
14 {
15     a+=b;
16     if(a>=mod) return a-mod;
17     return a;
18 }
19 
20 int dec (int a,int b)
21 {
22     a-=b;
23     if(a<0) return a+mod;
24     return a;
25 }
26 
27 int qui (int a,int b)
28 {
29     int s=1;
30     while(b)
31     {
32         if(b&1) s=1LL*s*a%mod;
33         a=1LL*a*a%mod;
34         b>>=1;
35     }
36     return s;
37 }
38 
39 void NTT (int *f,int v)
40 {
41     for (R i=1;i<=len;++i)
42         if(i<rev[i]) swap(f[i],f[ rev[i] ]);
43     for (R i=2;i<=len;i<<=1)
44     {
45         int ln=i/2,og1=qui((v==1)?3:inv_g,(mod-1)/i);
46         for (R b=0;b<len;b+=i)
47         {
48             int og=1;
49             for (R x=b;x<b+ln;++x)
50             {
51                 int t=1LL*og*f[x+ln]%mod;
52                 f[x+ln]=dec(f[x],t);
53                 f[x]=add(f[x],t);
54                 og=1LL*og*og1%mod;
55             }
56         }
57     }
58     if(v==1) return ;
59     int inv=qui(len,mod-2);
60     for (R i=0;i<=len;++i) f[i]=1LL*f[i]*inv%mod;
61 }
62 
63 int main()
64 {
65     scanf("%d",&n);
66     fac[0]=1; for (R i=1;i<=n;++i) fac[i]=1LL*i*fac[i-1]%mod;
67     inv[n]=qui(fac[n],mod-2);
68     for (R i=n;i>=1;--i) inv[i-1]=1LL*inv[i]*i%mod;
69     len=1; while(len<=2*(n+1)) len<<=1;
70     for (R i=0;i<=n;++i)
71     {
72         if(i&1) f[i]=mod-inv[i]; else f[i]=inv[i];
73         g[i]=1LL*qui(i,n)*inv[i]%mod;
74     }
75     for (R i=1;i<=len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)?(len>>1):0);
76     NTT(f,1); NTT(g,1);
77     for (R i=0;i<=len;++i) f[i]=1LL*f[i]*g[i]%mod;
78     NTT(f,-1);
79     for (R i=0;i<=n;++i) printf("%d ",f[i]);
80     return 0;
81 }
第二类斯特林数·行

 

 

第一类斯特林数·行

 

第二类斯特林数·列

 

第一类斯特林数·列

以上是关于斯特林数的计算方法的主要内容,如果未能解决你的问题,请参考以下文章

一份数论试卷

斯特林数的两个公式

OI关于斯特林数的简单理解

斯特林数欧拉数的求和技术及应用

带边数的无向连通图计数

带边数的无向连通图计数