[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:\n",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\n",a[read()]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhoushuyu/p/9068072.html