题面
题意:n个有标号点的图,问所有方案所有点度数的k次方的和。
前置技能:用ntt求一行第二类斯特林数
设点的度数为d,则它的系数为 n∗2(n−2)∗(n−1)/2∗Cdn−1 n ∗ 2 ( n − 2 ) ∗ ( n − 1 ) / 2 ∗ C n − 1 d ,贡献为 dk d k
根据出题人的理解,拆
dk
d
k
然后代进去画柿子,就出来
大概是这样吧。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;
const LL p=998244353;
const int N=800800;
int n,rev[N];
LL cheng(LL a,LL b)
{
LL res=1ll;
for(;b;b>>=1,a=a*a%p)
if(b&1)
res=res*a%p;
return res;
}
void init(int lim)
{
n=1;
int k=-1;
while(n<lim)
n<<=1,k++;
for(int i=0;i<n;i++)
rev[i]=(rev[i>>1]>>1) | ((i&1)<<k);
}
void ntt(LL *a,int ops)
{
for(int i=0;i<n;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int m=1,l=2;l<=n;m<<=1,l<<=1)
{
LL wn=(ops) ? cheng(3,(p-1)/l) : cheng(3,p-1-(p-1)/l);
for(int i=0;i<n;i+=l)
{
LL w=1ll;
for(int k=0;k<m;k++)
{
LL t=a[i+k+m]*w%p;
a[i+k+m]=(a[i+k]-t+p)%p;
a[i+k]=(a[i+k]+t)%p;
w=w*wn%p;
}
}
}
if(!ops)
{
LL Inv=cheng(n,p-2);
for(int i=0;i<n;i++)
a[i]=a[i]*Inv%p;
}
}
LL nn,kk;
LL jc[N],I[N],Ijc[N];
LL aa[N],bb[N],ans;
int main()
{
cin>>nn>>kk;
I[1]=Ijc[0]=jc[0]=1;
for(int i=2;i<=kk;i++)
I[i]=I[p%i]*(p-p/i)%p;
for(int i=1;i<=kk;i++)
jc[i]=jc[i-1]*i%p,Ijc[i]=Ijc[i-1]*I[i]%p;
for(int i=0;i<=kk;i++)
aa[i]=Ijc[i];
for(int i=0;i<=kk;i++)
if(i&1)
aa[i]=(p-aa[i])%p;
for(int i=0;i<=kk;i++)
bb[i]=cheng(i,kk)*Ijc[i]%p;
init(kk*2+3);
ntt(aa,1);
ntt(bb,1);
for(int i=0;i<n;i++)
aa[i]=aa[i]*bb[i]%p;
ntt(aa,0);
int tu=min(nn-1,kk);
LL now=1;
for(LL i=0;i<=tu;i++)
{
ans=(ans+now*cheng(2ll,nn-1-i)%p*aa[i])%p;
now=now*(nn-1-i)%p;
}
ans=ans*nn%p*cheng(2,(nn-2)*(nn-1)/2)%p;
cout<<ans<<endl;
return 0;
}