bzoj 5093 [Lydsy1711月赛]图的价值 NTT+第二类斯特林数

[Lydsy1711月赛]图的价值

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 245  Solved: 128
[Submit][Status][Discuss]

Description

“简单无向图”是指无重边、无自环的无向图(不一定连通)。
一个带标号的图的价值定义为每个点度数的k次方的和。
给定n和k,请计算所有n个点的带标号的简单无向图的价值之和。
因为答案很大,请对998244353取模输出。
 

Input

第一行包含两个正整数n,k(1<=n<=10^9,1<=k<=200000)。
 

Output

 输出一行一个整数,即答案对998244353取模的结果。

 

Sample Input

6 5

Sample Output

67584000

HINT

 

Source

本OJ付费获取

 

因为第二类斯特林数m>n的时候为0,所以就优化成,k log k了,主要就是计算第二类斯特林数,后面组合那里因为最多k

所以就是n-k+1项的反过来乘就可以处理了,然后还有ksm一下。

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 
 7 #define ll long long
 8 #define mod 998244353
 9 #define G 3
10 #define N 200007
11 using namespace std;
12 inline int read()
13 {
14     int x=0,f=1;char ch=getchar();
15     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
16     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
17     return x*f;
18 }
19 
20 int n,k,num,L,ans,inv;
21 int jc[N],jcf[N],ny[N];
22 int a[N<<2],b[N<<2],rev[N<<2];
23 
24 int ksm(int a,ll b)
25 {
26     int ans=1;
27     while(b)
28     {
29         if (b&1) ans=(ll)ans*a%mod;
30         a=(ll)a*a%mod;
31         b>>=1;
32     }
33     return ans;
34 }
35 void init()
36 {
37     jc[0]=jcf[0]=ny[0]=1;
38     for (int i=1;i<=k;i++)
39         jc[i]=(ll)jc[i-1]*i%mod,ny[i]=ksm(i,mod-2),ny[i]=(ll)ny[i]*ny[i-1]%mod;
40     for (int i=0;i<=k;i++)
41         a[i]=1ll*((i&1)?(-1):1)*ny[i],b[i]=(ll)ksm(i,k)*ny[i]%mod;
42     for (int i=1;i<=k;i++) jcf[i]=(ll)jcf[i-1]*(n-i+1)%mod;
43     for (num=1;num<=k*2;num<<=1,L++);if (L) L--;
44     inv=ksm(num,mod-2);
45     for (int i=0;i<num;i++)
46         rev[i]=(rev[i>>1]>>1)|((i&1)<<L);
47 }
48 void NTT(int *a,int flag)
49 {
50     for (int i=0;i<num;i++)
51         if (i<rev[i]) swap(a[i],a[rev[i]]);
52     for (int i=1;i<num;i<<=1)
53     {
54         int wn=ksm(G,(mod-1)/(i<<1));
55         for (int j=0;j<num;j+=(i<<1))
56         {
57             int w=1;
58             for (int k=0;k<i;w=(ll)w*wn%mod,k++)
59             {
60                 int x=a[j+k],y=(ll)w*a[j+k+i]%mod;
61                 a[j+k]=(x+y)%mod,a[j+k+i]=(x-y<0)?x-y+mod:x-y;        
62             }
63         }
64     }
65     if (flag==-1)
66     {
67         for (int i=1;i<num/2;i++) swap(a[i],a[num-i]);
68         for (int i=0;i<num;i++) a[i]=(ll)a[i]*inv%mod;
69     }
70 }
71 int main()
72 {
73     n=read(),k=read(),n--;
74     init();
75     NTT(a,1),NTT(b,1);
76     for (int i=0;i<num;i++)
77         a[i]=(ll)a[i]*b[i]%mod;
78     NTT(a,-1);
79     for (int i=0;i<=min(n,k);i++)
80         (ans+=(ll)a[i]*jc[i]%mod*ksm(2,n-i)%mod*jcf[i]%mod*ny[i]%mod)%=mod;
81     ans=(ll)ans*(n+1)%mod*ksm(2,(ll)(n-1)*n/2)%mod;
82     printf("%d
",ans);
83 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8659061.html