【CSU1911】Card Game(FWT)

【CSU1911】Card Game(FWT)

题面

vjuge
题目大意:
给定两个含有\(n\)个数的数组
每次询问一个数\(x\),回答在每个数组中各选一个数,或起来之后的结果恰好为\(x\)的方案数。

题解

\(FWT\)的模板题
\(FWT\)写起来是真的舒服

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
inline int gi()
{
    int x=0;char ch[20];
    scanf("%s",ch+1);
    for(int i=1,l=strlen(ch+1);i<=l;++i)x=(x<<1)+(ch[i]-48);
    return x;
}
int n,m,Q,N;
ll a[1<<19],b[1<<19];
void FWT(ll *P,int opt)
{
    for(int i=2;i<=N;i<<=1)
        for(int p=i>>1,j=0;j<N;j+=i)
            for(int k=j;k<j+p;++k)
                P[k+p]+=P[k]*opt;
}
int main()
{
    int T=read();
    for(int tt=1;tt<=T;++tt)
    {
        printf("Case #%d:\n",tt);
        n=read();m=read();N=1<<m;
        memset(a,0,sizeof(a));memset(b,0,sizeof(b));
        for(int i=1;i<=n;++i)a[gi()]++;
        for(int i=1;i<=n;++i)b[gi()]++;
        FWT(a,1);FWT(b,1);
        for(int i=0;i<N;++i)a[i]*=b[i];
        FWT(a,-1);Q=read();
        while(Q--)printf("%lld\n",a[gi()]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cjyyb/p/9064563.html
FWT