简单题意
一个带标号的图的价值定义为每个点度数的
k
(
<
=
2
e
5
)
k(<=2e5)
k(<=2e5)次方的和。
n
(
<
=
1
e
9
)
n(<=1e9)
n(<=1e9)个点的带标号的简单无向图的价值之和
(
m
o
d
998244353
)
\pmod {998244353}
(mod998244353)
题解
每个点只有标号之别,故只需要求出一个点的价值之和
×
n
\times n
×n即可。
a
n
s
=
n
∗
2
C
(
n
−
1
,
2
)
∗
∑
i
=
0
n
−
1
C
(
n
−
1
,
i
)
∗
i
k
∑
i
=
0
n
−
1
C
(
n
−
1
,
i
)
∗
i
k
=
∑
i
=
0
n
−
1
C
(
n
−
1
,
i
)
∗
∑
j
=
0
k
s
t
r
2
(
k
,
j
)
∗
j
!
∗
C
(
i
,
j
)
=
∑
j
=
0
k
s
t
r
2
(
k
,
j
)
∗
j
!
∗
∑
i
=
j
n
−
1
C
(
n
−
1
,
i
)
∗
C
(
i
,
j
)
=
∑
j
=
0
k
s
t
r
2
(
k
,
j
)
∗
j
!
∗
C
(
n
−
1
,
j
)
∗
∑
i
=
0
n
−
1
−
j
C
(
n
−
1
−
j
,
i
)
=
∑
j
=
0
k
s
t
r
2
(
k
,
j
)
∗
j
!
∗
C
(
n
−
1
,
j
)
∗
2
n
−
1
−
j
\begin{aligned} &ans =n * 2^{C(n-1,2)}*\sum_{i=0}^{n-1} C(n-1,i) * i^k\\ &\sum_{i=0}^{n-1} C(n-1,i) * i^k = \sum_{i=0}^{n-1} C(n-1,i) * \sum_{j=0}^{k} str2(k,j) * j! * C(i,j)\\ &=\sum_{j=0}^{k}str2(k,j) * j! * \sum_{i=j}^{n-1}C(n-1,i) * C(i,j)\\ &=\sum_{j=0}^{k}str2(k,j) * j! * C(n-1,j) * \sum_{i=0}^{n-1-j} C(n-1-j,i)\\ &=\sum_{j=0}^{k}str2(k,j) * j! * C(n-1,j) * 2^{n-1-j} \end{aligned}
ans=n∗2C(n−1,2)∗i=0∑n−1C(n−1,i)∗iki=0∑n−1C(n−1,i)∗ik=i=0∑n−1C(n−1,i)∗j=0∑kstr2(k,j)∗j!∗C(i,j)=j=0∑kstr2(k,j)∗j!∗i=j∑n−1C(n−1,i)∗C(i,j)=j=0∑kstr2(k,j)∗j!∗C(n−1,j)∗i=0∑n−1−jC(n−1−j,i)=j=0∑kstr2(k,j)∗j!∗C(n−1,j)∗2n−1−j
计算第二类斯特林数即可。
容斥原理可得:
s
t
r
2
(
n
,
k
)
=
1
k
!
∑
i
=
0
k
C
(
k
,
i
)
∗
(
k
−
i
)
n
∗
(
−
1
)
i
=
∑
i
=
0
k
(
−
1
)
i
i
!
∗
(
k
−
i
)
n
(
k
−
i
)
!
str2(n,k) = \frac 1{k!}\sum_{i=0}^k C(k,i) * (k-i)^n*(-1)^i = \sum_{i=0}^k\frac {(-1)^i}{i!}*\frac {(k-i)^n}{(k-i)!}
str2(n,k)=k!1∑i=0kC(k,i)∗(k−i)n∗(−1)i=∑i=0ki!(−1)i∗(k−i)!(k−i)n
化为EGF就行了。
F
F
T
O
(
n
log
n
)
FFT \ O(n \log n)
FFT O(nlogn)
AC Code:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define maxn 600005
#define mod 998244353
#define LL long long
using namespace std;
int n,k;
const int inv2 = (mod + 1) / 2;
int w[maxn]={1},r[maxn],lg[maxn],wlen,inv[maxn]={1,1},fac[maxn]={1,1},invf[maxn]={1,1};
int Pow(int base,LL k)
{
int ret = 1;
for(;k;k>>=1,base=1ll*base*base%mod)
if(k&1)
ret = 1ll * ret * base % mod;
return ret;
}
void Init(int n)
{
for(wlen=1;n>=2*wlen;wlen<<=1);
for(int i=1,pw=Pow(3,(mod-1)/(2*wlen));i<=2*wlen;i++) w[i] = 1ll * w[i-1] * pw % mod;
for(int i=2;i<=2*wlen;i++)
lg[i] = lg[i>>1] + 1,
fac[i] = 1ll * fac[i-1] * i % mod,
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod,
invf[i] = 1ll * invf[i-1] * inv[i] %mod;
}
inline void NTT(int *A,int n,int tp)
{
int lgn = lg[n];
for(int i=1;i<n;i++) r[i] = (r[i>>1]>>1)|((i&1)<<(lgn-1));
for(int i=1;i<n;i++) if(i<r[i]) swap(A[i],A[r[i]]);
for(int L=2;L<=n;L<<=1)
for(int st=0,l=L>>1,inc=wlen/l;st<n;st+=L)
for(int k=st,x=0;k<st+l;k++,x+=inc)
{
int tmp = 1ll * (tp == 1 ? w[x] : w[2*wlen-x]) * A[k+l] % mod;
A[k+l] = (A[k] - tmp) % mod , A[k] = (A[k] + tmp) % mod;
}
if(tp == -1)
for(int i=0,inv=Pow(n,mod-2);i<n;i++)
A[i] = 1ll * A[i] * inv % mod;
}
inline int C(int a,int b){ return 1ll * fac[a] * invf[b] % mod * invf[a-b] % mod; }
int a[maxn],b[maxn],str[maxn];
int main()
{
scanf("%d%d",&n,&k);
Init(2*k);
for(int i=0;i<=k;i++) a[i] = (i&1?-1:1) * invf[i] , b[i] = 1ll * Pow(i,k) * invf[i] % mod;
int len = 1;
for(;2*k>=len;len<<=1);
NTT(a,len,1),NTT(b,len,1);
for(int i=0;i<len;i++) str[i] = 1ll * a[i] * b[i] % mod;
NTT(str,len,-1);
int ans = n * 1ll * Pow(2,1ll*(n-1)*(n-2)/2) % mod , sum = 0;
for(int i=0,C=1,pw=Pow(2,n-1);i<=k;pw=1ll*pw*inv2%mod,C=1ll*C*(n-1-i)%mod*inv[i+1]%mod,i++)
sum = (sum + 1ll * str[i] * fac[i] % mod * C % mod * pw % mod) % mod;
printf("%lld\n",(1ll*sum*ans%mod+mod)%mod);
}