题目大意:求所有
n
n
n个点带标号竞赛图的强连通分量大小的
k
k
k次方之和的和,对
9982443535
9982443535
9982443535模数取模。
n
≤
1
0
5
,
k
≤
998244352
n\le10^5,k\le 998244352
n≤105,k≤998244352。
题解:
竞赛图缩点后拓扑序唯一(其实是链状结构然后剩下的两端不在同一个强连通分量里面的边的方向是确定的)。
设
g
n
g_n
gn表示答案,
f
n
f_n
fn表示
n
n
n个点的能够缩成一个点的竞赛图数量,
h
n
=
2
(
n
2
)
h_n=2^{\binom{n}{2}}
hn=2(2n)就是图的总数。
那么求
g
g
g显然是,你枚举拓扑序最后一坨点的大小,钦定它们是一个
S
C
C
SCC
SCC:
g
n
=
∑
i
=
1
n
(
n
i
)
(
h
n
−
i
i
k
+
g
n
−
i
)
f
i
g_n=\sum_{i=1}^n \binom ni \left(h_{n-i}i^k+g_{n-i}\right)f_i
gn=i=1∑n(in)(hn−iik+gn−i)fi
求
f
f
f更简单,用总数减去不合法的即可:
f
n
=
h
n
−
∑
i
=
1
n
−
1
(
n
i
)
h
n
−
i
f
i
f_n=h_n-\sum_{i=1}^{n-1}\binom{n}{i}h_{n-i}f_i
fn=hn−i=1∑n−1(in)hn−ifi
这样就可以做到
O
(
n
2
)
O\left(n^2\right)
O(n2)
接下来开始多项式的套路:
首先关于
f
f
f,有:
h
n
=
∑
i
=
1
n
(
n
i
)
f
i
h
n
−
i
=
∑
i
=
0
n
(
n
i
)
f
i
h
n
−
i
+
[
n
=
=
0
]
h_n=\sum_{i=1}^n\binom nif_ih_{n-i}=\sum_{i=0}^n\binom nif_ih_{n-i}+[n==0]
hn=i=1∑n(in)fihn−i=i=0∑n(in)fihn−i+[n==0]并钦定
f
0
=
0
f_0=0
f0=0
那么令:
H
(
x
)
=
∑
i
≥
0
h
i
i
!
x
i
,
F
(
x
)
=
∑
i
≥
1
f
i
i
!
x
i
H(x)=\sum_{i\geq 0}\frac {h_i}{i!}x^i,F(x)=\sum_{i\geq1}\frac{f_i}{i!}x^i
H(x)=i≥0∑i!hixi,F(x)=i≥1∑i!fixi
那么
H
=
F
H
+
1
,
F
=
1
−
H
−
1
H=FH+1,F=1-H^{-1}
H=FH+1,F=1−H−1
然后由之前的式子,令:
G
(
x
)
=
∑
i
≥
1
g
i
i
!
x
i
,
T
(
x
)
=
∑
i
≥
1
f
i
i
k
i
!
x
i
G(x)=\sum_{i\geq1}\frac{g_i}{i!}x^i,T(x)=\sum_{i\geq1}\frac{f_ii^k}{i!}x^i
G(x)=i≥1∑i!gixi,T(x)=i≥1∑i!fiikxi
则:
G
=
H
T
+
G
F
,
(
1
−
F
)
G
=
H
T
,
G
=
H
T
1
−
F
=
H
T
H
−
1
=
H
2
T
G=HT+GF,(1-F)G=HT,G=\frac{HT}{1-F}=\frac{HT}{H^{-1}}=H^2T
G=HT+GF,(1−F)G=HT,G=1−FHT=H−1HT=H2T
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define p 998244353
#define N 300010
#define clr(a,n) memset(a,0,sizeof(int)*((n)+1))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*((n)+1))
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int f[N],g[N],h[N],mi[N],fac[N],facinv[N],H[N],T[N],F[N],G[N];
inline int fast_pow(int x,lint k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
inline int C(int n,int m) { if(n<0||m<0||n<m) return 0;return (lint)fac[n]*facinv[m]%p*facinv[n-m]%p; }
inline int prelude(int n)
{
rep(i,fac[0]=1,n) fac[i]=(lint)fac[i-1]*i%p;
facinv[n]=fast_pow(fac[n],p-2);
for(int i=n-1;i>=0;i--) facinv[i]=facinv[i+1]*(i+1ll)%p;
return 0;
}
namespace NTT_space{
int a[N<<3],b[N<<3],r[N<<3];
inline int NTT(int *a,int n,int s)
{
rep(i,1,n-1) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=2;i<=n;i<<=1)
{
int wn=fast_pow(3,s>0?(p-1)/i:p-1-(p-1)/i);
for(int j=0,t=i>>1;j<n;j+=i)
for(int k=0,w=1,x,y;k<t;k++,w=(lint)w*wn%p)
x=a[j+k],y=(lint)w*a[j+k+t]%p,
a[j+k]=x+y,(a[j+k]>=p?a[j+k]-=p:0),
a[j+k+t]=x-y,(a[j+k+t]<0?a[j+k+t]+=p:0);
}
if(s<0) for(int i=0,ninv=fast_pow(n,p-2);i<n;i++) a[i]=(lint)a[i]*ninv%p;
return 0;
}
inline int tms(int *A,int *B,int *C,int m1,int m2)
{
int n=1,L=0;for(;n<=m1+m2;n<<=1,L++);
rep(i,1,n-1) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
clr(a,n),cpy(a,A,m1),NTT(a,n,1);
clr(b,n),cpy(b,B,m2),NTT(b,n,1);
rep(i,0,n-1) a[i]=(lint)a[i]*b[i]%p;
return NTT(a,n,-1),cpy(C,a,m1+m2),0;
}
inline int tms(int *A,int *B,int *C,int n) { return tms(A,B,C,n,n); }
}
using NTT_space::tms;
namespace POLYINV_space{
int f[N<<3],g[N<<3],h[N<<3];
inline int polyinv(int *F,int *G,int m)
{
int n=1;while(n<m) n<<=1;
clr(f,n),cpy(f,F,m),clr(g,n),g[0]=fast_pow(f[0],p-2);
for(int i=2;i<=n;i<<=1)
{
rep(j,0,i>>1) h[j]=g[j]<<1,(h[j]>=p?h[j]-=p:0);
tms(g,g,g,i>>1),tms(g,f,g,i);
rep(j,0,i-1) g[j]=h[j]-g[j],(g[j]<0?g[j]+=p:0);
clr(g+i,i);
}
return cpy(G,g,m),0;
}
}
using POLYINV_space::polyinv;
int main()
{
int n,k;scanf("%d%d",&n,&k);prelude(n);
rep(i,0,n) h[i]=fast_pow(2,i*(i-1ll)/2),H[i]=(lint)h[i]*facinv[i]%p,mi[i]=fast_pow(i,k);
// rep(i,1,n) { f[i]=h[i];for(int j=1;j<i;j++) f[i]-=(lint)f[j]*h[i-j]%p*C(i,j)%p,(f[i]<0?f[i]+=p:0); } rep(i,1,n) F[i]=(lint)f[i]*facinv[i]%p;
// rep(i,1,n) rep(j,1,i) g[i]+=(lint)f[j]%p*(g[i-j]+(lint)mi[j]*h[i-j]%p)%p*C(i,j)%p,(g[i]>=p?g[i]-=p:0);printf("%d\n",g[n]);
polyinv(H,F,n);rep(i,0,n) F[i]=(p-F[i])%p;(F[0]+=1)%=p; rep(i,1,n) T[i]=(lint)F[i]*mi[i]%p;
tms(H,H,H,n),tms(H,T,G,n);return !printf("%lld\n",(lint)G[n]*fac[n]%p);
}