#FWT#ABC367 G - Sum of (XOR^K or 0)

题目

给定一个长度为 n 的序列 a,求所有长度为 m 的倍数的子序列异或和的 k 次方之和。


分析

首先异或和以及 k 次方进行分离,应该先求出每种异或和对应的方案数,再赋以 k 次方。

抽象一点也就是 i=02o1[xiy0]ikj=1n(1+xajy),其中 x 是异或卷积,y 是针对 m 的循环卷积。

如果直接 n 个多项式相乘显然不行,观察对于 1(x0) 经过 FWT 后为全 1 的序列,而 xaj 经过 FWT 后为 ±1 的序列,

那么进行 FWT 后,后面的式子实际是 [y0](1+y)c(1y)nc,也就转化成求有多少个 aj 经过 FWT 变换能在 i 的位置产生 1

由于 FWT 的线性性,将 ai 对应位置加一得到的 f 数组进行 FWT 后,c(nc)=fi,那么就能把 c 解出来。

对于 y 的卷积可以在 O(nm) 的时间预处理,那么代入该式子后进行逆 FWT 即可。


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
const int mod=998244353,inv=499122177,N=1048576;
int f[N],n,m,k,cnt,mx,ans,mi[N],prime[N],dp[N],g0[N][111],g1[N][111],Cnt; 
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans; 
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
int mo1(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int mo2(int x,int y){return x<y?x-y+mod:x-y;}
void FWT_XOR(int *f,int opt){
	for (int p=2;p<=n;p<<=1){
		int len=p>>1;
		for (int i=0;i<n;i+=p)
		    for (int j=i;j<i+len;++j){
		    	int t1=f[j],t2=f[j+len];
		    	f[j]=mo1(t1,t2),f[j+len]=mo2(t1,t2);
		    	if (opt==-1) f[j]=1ll*f[j]*inv%mod,
		    	    f[j+len]=1ll*f[j+len]*inv%mod;
			}
	}
}
int ksm(int x,int y){
	int ans=1;
	for (;y;y>>=1,x=1ll*x*x%mod)
	    if (y&1) ans=1ll*ans*x%mod;
	return ans;
}
int main(){
    cnt=iut(),m=iut(),k=iut();
    for (int i=0;i<cnt;++i){
		int x=iut();
		mx=max(mx,x);
		++f[x];
	}
	for (n=1;n<=mx;n<<=1);
    mi[1]=1;
	for (int i=2;i<=n-1;++i){
		if (!mi[i]) mi[i]=ksm(i,k),prime[++Cnt]=i;
		for (int j=1;j<=Cnt&&prime[j]<=(n-1)/i;++j){
			mi[i*prime[j]]=1ll*mi[i]*mi[prime[j]]%mod;
			if (i%prime[j]==0) break;
		}
	}
	FWT_XOR(f,1);
	g0[0][0]=g1[0][0]=1;
	for (int i=1;i<=cnt;++i){
		for (int j=0;j<m;++j){
			g0[i][j==m-1?0:(j+1)]=mo1(g0[i-1][j==m-1?0:(j+1)],g0[i-1][j]);
			g1[i][j==m-1?0:(j+1)]=mo2(g1[i-1][j==m-1?0:(j+1)],g1[i-1][j]);
		}
	}
	for (int i=0;i<=cnt;++i){
		dp[i]=1ll*g0[i][0]*g1[cnt-i][0]%mod;
		for (int j=1;j<m;++j)
		    dp[i]=mo1(dp[i],1ll*g0[i][j]*g1[cnt-i][m-j]%mod);
	}
	for (int i=0;i<n;++i) f[i]=dp[((cnt+f[i])%mod)>>1];
	FWT_XOR(f,-1);
	for (int i=1;i<n;++i) ans=mo1(ans,1ll*mi[i]*f[i]%mod);
	return !printf("%d",ans);
}
posted @   lemondinosaur  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示