【xsy1301】 原题的价值 组合数+斯特林数+FFT

题目大意:求n×2(n1)(n2)/22n1i=0(n1i)ik

数据范围:n109k105,答案对998244353取模。


 

我们令F(n,k)=n1i=0(n1i)ik

那么最终要输出的东西显然就是n×2(n1)(n2)/22F(n,k)

我们令G(n,k)=(n1)k_2n1k

 

我们先考虑下当k=0的时候要怎么做,我们显然有:

F(n,0)=n1i=0(n1i)=2n1

化简是根据二项式定理来的,在此不展开说了。

 

考虑下当k=1的时候要怎么做:

F(n,1)=n1i=0(n1i)i=n1i=0(n1)!i!(n1i)!i=n1i=1(n1)!(i1)!(n1i)!=n1i=1(n1)!(i1)!((n2)(i1))!=(n1)n1i=1(n2)!(i1)!((n2)(i1))!=n1)n1i=1(n2i1)=(n1)F(n1,0)=G(n,1)

 

我们考虑按照k=1的化简方法来化简k=2,由于跟上文比较相似,所以可能会有不少的跳步

F(n,2)=n1i=0(n1i)i2

=n1i=0(n1)!i!(n1i)!i2

=(n1)n1i=1(n2i1)i

=(n1)n1i=1(n2)!(i1)!((n2)(i1))!((i1)+1)

=F(n1,1)+(n1)n1i=1(n2)!(i2)!((n3)(i2))!

=F(n1,1)+(n1)(n2)n1i=1(n3)!(i2)!((n3)(i2))!

=F(n1,1)+(n1)(n2)F(n2,0)

=G(n,1)+G(n,2)

 

 
根据k=2的推法,我们推出了k=3k=4的情况:

F(n,3)=G(n,1)+3G(n,2)+4G(n,3)

F(n,4)=G(n,1)+7G(n,2)+6G(n,3)+G(n,4)

诶?这不是斯特林三角形吗(证明显然,这里不证了)

 

于是有:

F(n,m)=mi=1S2(n,i)G(n,i)

G(n,1k)可以在O(k)的时间复杂度内求出来,S2(n,1k)可以在O(klog k)的复杂度内用FFT求出来。

完结撒花~

 

 

复制代码
 1 #include<bits/stdc++.h>
 2 #define MOD 998244353
 3 #define L long long
 4 #define M (1<<18)
 5 #define G 3
 6 using namespace std;
 7 
 8 L fac[M]={0},invfac[M]={0};
 9 L pow_mod(L x,L k){L ans=1;for(;k>0;k>>=1,x=x*x%MOD) if(k&1) ans=ans*x%MOD; return ans;}
10 L C(int n,int m){return fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;}
11 
12 void change(L a[],int n){
13     for(int i=0,j=0;i<n-1;i++){
14         if(i<j) swap(a[i],a[j]);
15         int k=n>>1;
16         while(j>=k) j-=k,k>>=1;
17         j+=k;
18     }
19 }
20 void NTT(L a[],int n,int on){
21     change(a,n);
22     for(int h=2;h<=n;h<<=1){
23         L wn=pow_mod(G,(MOD-1)/h);
24         for(int j=0;j<n;j+=h){
25             L w=1;
26             for(int k=j;k<j+(h>>1);k++){
27                 L u=a[k],t=a[k+(h>>1)]*w%MOD;
28                 a[k]=(u+t)%MOD;
29                 a[k+(h>>1)]=(u-t+MOD)%MOD;
30                 w=w*wn%MOD;
31             }
32         }
33     }
34     if(on==-1){
35         reverse(a+1,a+n);
36         L INV=pow_mod(n,MOD-2);
37         for(int i=0;i<n;i++) a[i]=a[i]*INV%MOD;
38     }
39 }
40 L a[M]={0},b[M]={0},s[M]={0},nc[M]={0};
41 
42 int main(){
43     fac[0]=1; for(int i=1;i<M;i++) fac[i]=fac[i-1]*i%MOD;
44     invfac[M-1]=pow_mod(fac[M-1],MOD-2);
45     for(int i=M-2;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD;
46     L n,k,ans=0; cin>>n>>k;
47     if(k==0) return printf("%lld\n",n*pow_mod(2,(n-1)*n/2)%MOD);
48     for(L i=0,mul=1;i<k;i++){
49         mul=mul*(n-i-1)%MOD;
50         nc[i+1]=mul*pow_mod(2,n-i-2)%MOD;
51     }
52     for(int i=0;i<=k;i++){
53         a[i]=pow_mod(MOD-1,i)*invfac[i]%MOD;
54         b[i]=pow_mod(i,k)*invfac[i]%MOD;
55     }
56     int len=1; while(k*2>=len) len<<=1;
57     NTT(a,len,1); NTT(b,len,1);
58     for(int i=0;i<len;i++) s[i]=a[i]*b[i]%MOD;
59     NTT(s,len,-1);
60     for(int i=k+1;i<len;i++) s[i]=0;
61     
62     for(int i=1;i<=k;i++)
63     (ans+=nc[i]*s[i])%=MOD;
64     
65     cout<<ans*n%MOD*pow_mod(2,(n*(n-1)/2-(n-1)))%MOD<<endl;
66 }
复制代码

 

posted @   AlphaInf  阅读(317)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示