[bzoj5093]图的价值
每个点计算贡献,有n-1的点的图的总数,然后若干次方转成下降幂再斯特林数求行就能统计答案了。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
const int mod=998244353;
int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
int sub(int a,int b){a-=b;return a<0?a+mod:a;}
int mul(int a,int b){return (ll)a*b%mod;}
int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
int mul(int a,int b,int mod){return (ll)a*b%mod;}
int qpow(int a,int b,int mod){int ret=1;for(;b;b>>=1,a=mul(a,a,mod))if(b&1)ret=mul(ret,a,mod);return ret;}
/*math*/
namespace Template_Poly{
const int g=3;
typedef vector<int> Poly;
int rev[N];
Poly Poly_add(Poly A,Poly B){
A.resize(max(A.size(),B.size()));
for(size_t i=0;i<B.size();i++)A[i]=add(A[i],B[i]);
return A;
}
void DFT(int *t,int n,int type){
int l=0;while(1<<l<n)++l;
for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<n;i++)if(rev[i]>i)swap(t[rev[i]],t[i]);
for(int step=1;step<n;step<<=1){
int wn=qpow(g,(mod-1)/(step<<1));
for(int i=0;i<n;i+=step<<1){
int w=1;
for(int k=0;k<step;k++,w=mul(w,wn)){
int x=t[i+k],y=mul(t[i+k+step],w);
t[i+k]=add(x,y),t[i+k+step]=sub(x,y);
}
}
}
if(type==1)return;
for(int i=1;i<n-i;i++)swap(t[i],t[n-i]);
int inv=qpow(n,mod-2);
for(int i=0;i<n;i++)t[i]=mul(t[i],inv);
}
Poly NTT(Poly A,int n,Poly B,int m){
static Poly res,PolA,PolB;
PolA=A,PolB=B;
int len=1;while(len <= n+m)len<<=1;
res.resize(len);
PolA.resize(len),PolB.resize(len);
DFT(&PolA[0],len,1);DFT(&PolB[0],len,1);
for(int i=0;i<len;i++) res[i]= mul(PolA[i],PolB[i]);
DFT(&res[0],len,-1);
res.resize(n+m-1);
return res;
}
Poly NTT(Poly A,Poly B){
return NTT(A,A.size(),B,B.size());
}
Poly Poly_inv(Poly A,int n){
if(n==1)return Poly(1,qpow(A[0],mod-2));
int len=1<<((int)ceil(log2(n))+1);
Poly x=Poly_inv(A,(n+1)>>1),y;
x.resize(len),y.resize(len);
for(int i=0;i<n;i++)y[i]=A[i];
DFT(&x[0],len,1),DFT(&y[0],len,1);
for(int i=0;i<len;i++)x[i]=mul(x[i],sub(2,mul(x[i],y[i])));
DFT(&x[0],len,-1);
x.resize(n);
return x;
}
Poly Poly_inv(Poly A){
return Poly_inv(A,A.size());
}
Poly Deri(Poly A){
int n=A.size();
for(int i=1;i<n;i++)A[i-1]=mul(A[i],i);
A.resize(n-1);
return A;
}
Poly Inte(Poly A){
int n=A.size();
A.resize(n+1);
for(int i=n;i;i--)A[i]=mul(A[i-1],qpow(i,mod-2));
A[0]=0;
return A;
}
Poly ln(Poly A){
int len=A.size();
A=Inte(NTT(Deri(A),Poly_inv(A)));
A.resize(len);
return A;
}
Poly exp(Poly A,int n){
if(n==1)return Poly(1,1);
Poly x=exp(A,(n+1)>>1),y;
x.resize(n);
y=ln(x);
for(int i=0;i<n;i++)y[i]=sub(A[i],y[i]);
y[0]++;
x=NTT(x,y);
x.resize(n);
return x;
}
Poly exp(Poly A){
return exp(A,A.size());
}
Poly sqrt(Poly A,int n){
if(n==1)return Poly(1,1);
Poly x=sqrt(A,(n+1)>>1),y;
x.resize(n),y.resize(n);
for(int i=0;i<n;i++)y[i]=A[i];
x=Poly_add(NTT(Poly_inv(x),y),x);
int inv2=qpow(2,mod-2);
for(int i=0;i<n;i++)
x[i]=mul(x[i],inv2);
x.resize(n);
return x;
}
Poly sqrt(Poly A){
return sqrt(A,A.size());
}
}
using namespace Template_Poly;
typedef long long ll;
int n,k;
int f[N*2];
Poly L,R;
Poly S;
int main()
{
scanf("%d%d",&n,&k);
L.resize(k+1);R.resize(k+1);
int _A=1;
int _fac=1;
for(int i=0;i<=k;i++){
if(i>0)_A=mul(_A,n-i);
if(i>0)_fac=mul(_fac,qpow(i,mod-2));
if(i>n-1)break;
int comb=mul(_A,_fac);
f[i]=mul(comb,qpow(2,n-i-1));
}
_fac=1;
for(int i=0;i<=k;i++){
if(i>0){
_fac=mul(_fac,qpow(i,mod-2));_fac=sub(0,_fac);
}L[i]=_fac;
}
_fac=1;
for(int i=0;i<=k;i++){
if(i>0)_fac=mul(_fac,qpow(i,mod-2));
R[i]=mul(_fac,qpow(i,k));
}
S=NTT(L,R);
int fac=1;
int ans=0;
for(int i=0;i<=k;i++){
if(i>0)fac=mul(fac,i);
ans=add(ans,mul(fac,mul(f[i],S[i])));
}
int ml=qpow(2,mul((n-2)%2?n-2:(n-2)/2,(n-1)%2?(n-1):(n-1)/2,mod-1));
ans=mul(ans,ml);ans=mul(ans,n);
printf("%d\n",ans);
}