[CSU1911]Card Game

vjudge

题意

两个数组({a_i})({b_i}),求从中分别选出两个数或运算结果为(x)的方案数。

sol

裸的FWT。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
#define ll long long
const int N = 1<<18;
int T,n,m,q,len;ll a[N],b[N];
int read(){
	char s[30];scanf("%s",s);int x=0;
	for (int i=0,l=strlen(s);i<l;++i) x=(x<<1)+s[i]-'0';
	return x;
}
void fwt(ll *P,int len,int opt){
	for (int i=1;i<len;i<<=1)
		for (int p=i<<1,j=0;j<len;j+=p)
			for (int k=0;k<i;++k)
				P[j+k+i]+=P[j+k]*opt;
}
void mul(ll *a,ll *b,int len){
	for (int i=0;i<len;++i) a[i]=a[i]*b[i];
}
int main(){
	T=gi();
	for (int zsy=1;zsy<=T;++zsy){
		printf("Case #%d:
",zsy);
		n=gi();m=gi();len=1<<m;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		for (int i=1;i<=n;++i) ++a[read()];
		for (int i=1;i<=n;++i) ++b[read()];
		fwt(a,len,1);fwt(b,len,1);mul(a,b,len);
		fwt(a,len,-1);
		q=gi();while (q--) printf("%lld
",a[read()]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/zhoushuyu/p/9068072.html