考虑计算一个点的贡献,最后 \(\times n\) 即为所求。
显然一个点的贡献为 \(\sum\limits_{i=0}^{n-1}\binom{n-1}ii^k2^{\frac{(n-1)(n-2)}2}\),则有:
\[\sum_{i=0}^{n-1}\binom{n-1}ii^k2^{\frac{(n-1)(n-2)}2}=2^{\frac{(n-1)(n-2)}2}\sum_{i=0}^{n-1}\sum_{j=0}^k\begin{Bmatrix}k\\j\end{Bmatrix}i^\underline j\binom{n-1}i \]\[=2^{\frac{(n-1)(n-2)}2}\sum_{j=0}^k\begin{Bmatrix}k\\j\end{Bmatrix}\sum_{i=0}^{n-1}i^\underline j\binom{n-1}i \]\[=2^{\frac{(n-1)(n-2)}2}\sum_{j=0}^k\begin{Bmatrix}k\\j\end{Bmatrix}(n-1)^\underline j\sum_{i=0}^{n-1}\binom{n-j-1}{i-j} \]\[=2^{\frac{(n-1)(n-2)}2}\sum_{j=0}^k\begin{Bmatrix}k\\j\end{Bmatrix}(n-1)^\underline j2^{n-j-1} \]利用第二类斯特林数·行的做法求解 \(\begin{Bmatrix}k\\j\end{Bmatrix}\) 即可做到 \(O(k\log k)\) 的时间复杂度。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=6e5+5,p=998244353;
namespace NTT{
int rev[N],mx,k,qp;
struct dft{int fg[N];};
int qpow(int x,int y){
int re=1;
while(y){
if(y&1) re=re*x%p;
x=x*x%p,y>>=1;
}return re;
}void init(int n){
mx=1,k=0,rev[0]=0;
while(mx<=n) mx*=2,k++;
for(int i=0;i<mx;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
qp=qpow(mx,p-2);
}void ntt(dft &a,int fl){
for(int i=0;i<mx;i++)
if(i<rev[i]) swap(a.fg[i],a.fg[rev[i]]);
for(int i=1;i<mx;i*=2){
int om=qpow(fl?3:(p+1)/3,(p-1)/(i<<1));
for(int j=0,w=1;j<mx;j+=i*2,w=1)
for(int k=j;k<j+i;k++,w=w*om%p){
int x=a.fg[k],y=w*a.fg[k+i]%p;
a.fg[k]=(x+y)%p,a.fg[k+i]=(x-y+p)%p;
}
}if(fl) return;
for(int i=0;i<mx;i++)
a.fg[i]=a.fg[i]*qp%p;
}
}using namespace NTT;
int n,m;dft f,g;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m,init(m*2+1);
for(int i=0,jc=1;i<=m;i++,jc=jc*i%p){
f.fg[i]=(1-i%2*2)*qpow(jc,p-2);
g.fg[i]=qpow(i,m)*qpow(jc,p-2)%p;
}ntt(f,1),ntt(g,1);
for(int i=0;i<mx;i++)
f.fg[i]=f.fg[i]*g.fg[i]%p;
ntt(f,0);int ans=0;
for(int i=0,dw=1;i<=m;i++,dw=dw*(n-i)%p)
ans=(ans+f.fg[i]*dw%p*qpow(2,n-i-1))%p;
ans=ans*qpow(2,(n-3)*n/2+1)%p*n%p;
return cout<<ans,0;
}
标签:begin,frac,int,题解,sum,Bmatrix,end,价值,BZOJ5093
From: https://www.cnblogs.com/chang-an-22-lyh/p/18687118/bzoj5093-tu_de_jia_zhi-tj