[atABC288Ex]A Nameless Counting Problem

\(f(n,m,x)\)为满足\(\begin{cases}a_{i}\in [0,m)\\\bigoplus_{i=1}^{n}a_{i}=x\\\forall i\ne j,a_{i}\ne a_{j}\end{cases}\)的序列\(\{a_{n}\}\)数,则答案即\(\sum_{0\le i\le \lfloor\frac{n}{2}\rfloor}{m+i-1\choose i}\frac{f(n-2i,m+1,x)}{(n-2i)!}\)

\(g_{k}(n,x)=f(n,2^{k},x)\),则\(g_{k}(n,x)=\begin{cases}[x=0]&n=0\\(n-1)!{2^{k}\choose n-1}-(n-1)(2^{k}-n+2)g_{k}(n-2,x)&n\ge 1\end{cases}\)

显然\(g_{k}(n,x)\)仅有\(x=0\)\(x\ne 0\)两种值,以下分别记为\(G_{k,0/1}(n)\)(预处理出)

\(f_{k}(n,m,x)=f(n,m\%2^{k},x\%2^{k})\),则

\[f_{k+1}(n,m,x)=\begin{cases}[x_{k}=0]f_{k}(n,m,x)&m_{k}=0\\\sum_{0\le i\le n,i\equiv x_{k}\pmod 2}{n\choose i}\sum_{y=0}^{2^{k}-1}g_{k}(n-i,y)f_{k}(i,m,x\oplus y)&m_{k}=1\end{cases} \]

(其中\(m_{k}\)\(x_{k}\)分别表示\(m,x\)二进制下第\(k\)位的值)

关于后者,注意到\(\sum_{y=0}^{2^{k}-1}f_{k}(i,m,x\oplus y)=i!{m\%2^{k}\choose i}\),则

\[f_{k+1}(n,m,x)=\sum_{0\le i\le n,i\equiv x_{k}\pmod 2}{n\choose i}\left(G_{k,1}(n-i)i!{m\%2^{k}\choose i}+(G_{k,0}(n-i)-G_{k,1}(n-i))f_{k}(i,m,x)\right) \]

显然可以NTT优化,时间复杂度为\(O(n\log n\log V)\)(其中\(V\)为值域)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
const int N=100005,mod=998244353;
int n,fac[N],inv[N],g[N][2],f[N];
ll m,x;vector<int>v1,v2,v3;
int add(int x,int y){
	x+=y;
	return (x<mod ? x : x-mod);
}
int qpow(int n,int m){
	int s=n,ans=1;
	while (m){
		if (m&1)ans=(ll)ans*s%mod;
		s=(ll)s*s%mod,m>>=1;
	}
	return ans;
}
namespace Poly{
	const int N=18;
	int n,tn,w[N][1<<N],iw[N][1<<N];
	void init(int g){
		for(int i=0;i<N;i++){
			w[i][0]=iw[i][0]=1;
			w[i][1]=qpow(g,(mod-1>>i+1));
			iw[i][1]=qpow(w[i][1],mod-2);
			for(int j=2;j<(1<<i);j++){
				w[i][j]=(ll)w[i][1]*w[i][j-1]%mod;
				iw[i][j]=(ll)iw[i][1]*iw[i][j-1]%mod;
			}
		}
	}
	void get_n(int m){
		n=1,tn=0;
		while (n<m)n<<=1,tn++;
	}
	void dft(int *a){
		for(int i=n,t=0;i>1;i>>=1,t++){
			int *W=w[tn-t-1];
			for(int j=0;j<n;j+=i)
				for(int k=0;k<(i>>1);k++){
					int x=a[j+k],y=a[j+k+(i>>1)];
					a[j+k]=add(x,y);
					a[j+k+(i>>1)]=(ll)(x-y+mod)*W[k]%mod;
				}
		}
	}
	void idft(int *a){
		for(int i=2,t=0;i<=n;i<<=1,t++){
			int *W=iw[t];
			for(int j=0;j<n;j+=i)
				for(int k=0;k<(i>>1);k++){
					int x=a[j+k],y=(ll)W[k]*a[j+k+(i>>1)]%mod;
					a[j+k]=add(x,y),a[j+k+(i>>1)]=add(x,mod-y); 
				}
		}
		int inv=qpow(n,mod-2);
		for(int i=0;i<n;i++)a[i]=(ll)inv*a[i]%mod;
	}
	vi mul(vi a,vi b,int ma,int mb,int m){
		if (ma<0)ma=a.size();
		if (mb<0)mb=b.size();
		if (m<0)m=ma+mb-1;
		ma=min(ma,m),mb=min(mb,m);
		get_n(ma+mb-1);
		a.resize(n),b.resize(n);
		for(int i=ma;i<n;i++)a[i]=0;
		for(int i=mb;i<n;i++)b[i]=0;
		dft(a.data()),dft(b.data());
		for(int i=0;i<n;i++)a[i]=(ll)a[i]*b[i]%mod;
		idft(a.data()),a.resize(m);
		return a;
	}
};
int main(){
	Poly::init(3);
	fac[0]=inv[0]=inv[1]=1;
	for(int i=1;i<N;i++)fac[i]=(ll)fac[i-1]*i%mod;
	for(int i=2;i<N;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
	for(int i=2;i<N;i++)inv[i]=(ll)inv[i-1]*inv[i]%mod;
	scanf("%d%lld%lld",&n,&m,&x);
	m++,v1.resize(n+1),v2.resize(n+1);
	g[0][0]=g[1][0]=g[1][1]=f[0]=1;
	for(int k=0;k<61;k++){
		int C=(1LL<<k)%mod,s=1;
		for(int i=2;i<=n;i++){
			if (i>(1LL<<k))g[i][0]=g[i][1]=0;
			else{
				s=(ll)s*(C-i+2)%mod;
				for(int p=0;p<2;p++)g[i][p]=(s+(ll)(mod-i+1)*(C-i+2)%mod*g[i-2][p])%mod;
			}
		}
		if ((m>>k)&1^1){
			if ((x>>k)&1)memset(f,0,sizeof(f));
		}
		else{
			C=(m&(1LL<<k)-1)%mod,s=1;
			for(int i=0;i<=n;i++){
				v1[i]=(ll)inv[i]*((i&1)==((x>>k)&1) ? s : 0)%mod;
				v2[i]=(ll)inv[i]*g[i][1]%mod;
				s=(ll)s*(C-i+mod)%mod;
			}
			v3=Poly::mul(v1,v2,-1,-1,-1);
			for(int i=0;i<=n;i++){
				v1[i]=(ll)inv[i]*((i&1)==((x>>k)&1) ? f[i] : 0)%mod;
				v2[i]=(ll)inv[i]*(g[i][0]-g[i][1]+mod)%mod;
				f[i]=v3[i];
			}
			v3=Poly::mul(v1,v2,-1,-1,-1);
			for(int i=0;i<=n;i++)f[i]=(ll)fac[i]*(f[i]+v3[i])%mod;
		}
	}
	int s=1;
	for(int i=0;i<=n;i++){
		if (i&1)v1[i]=0;
		else{
			v1[i]=(ll)s*inv[i>>1]%mod;
			s=(m+(i>>1))%mod*s%mod;
		}
		v2[i]=(ll)f[i]*inv[i]%mod;
	}
	v3=Poly::mul(v1,v2,-1,-1,-1);
	for(int i=1;i<=n;i++)printf("%d\n",v3[i]);
	return 0;
}
posted @ 2023-03-08 16:01  PYWBKTDA  阅读(105)  评论(0编辑  收藏  举报