CSU 1911 Card Game 快速沃尔什变换(FWT)模板题

来源:互联网 发布:敏捷网络的五个理念 编辑:程序博客网 时间:2024/06/05 14:11

题意:给你两个二进制数的集合,给出q次询问,输出两个集合之间元素或的值等于查询值的种数。

 

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define LL long longconst int maxn = 1<<18;LL a[maxn],b[maxn];int n,m;char s[20];void FWT(LL a[],int n){    for(int d=1;d<n;d<<=1)        for(int m=d<<1,i=0;i<n;i+=m)            for(int j=0;j<d;j++)            {                int x=a[i+j],y=a[i+j+d];                a[i+j+d]=x+y;            }}void UFWT(LL a[],int n){    for(int d=1;d<n;d<<=1)        for(int m=d<<1,i=0;i<n;i+=m)            for(int j=0;j<d;j++)            {                int x=a[i+j],y=a[i+j+d];                a[i+j+d]=y-x;            }}void solve(LL a[],LL b[],int n){    FWT(a,n);    FWT(b,n);    for(int i=0;i<n;i++) a[i]=a[i]*b[i];    UFWT(a,n);}int main(){    int t,q;    scanf("%d",&t);    for(int cas=1;cas<=t;cas++)    {        memset(a,0,sizeof a);        memset(b,0,sizeof b);        scanf("%d%d",&n,&m);        int l,x;        for(int i=0;i<n;i++)        {            x=0;            scanf("%s",s);            l=strlen(s);            for(int j=0;j<l;j++) x=(x<<1)+s[j]-'0';            a[x]++;        }        for(int i=0;i<n;i++)        {            x=0;            scanf("%s",s);            l=strlen(s);            for(int j=0;j<l;j++) x=(x<<1)+s[j]-'0';            b[x]++;        }        solve(a,b,(1<<m));        scanf("%d",&q);        printf("Case #%d:\n",cas);        while(q--)        {            scanf("%s",s);            x=0;            l=strlen(s);            for(int i=0;i<l;i++) x=(x<<1)+s[i]-'0';            printf("%lld\n",a[x]);        }    }    return 0;}


 

0 0
原创粉丝点击