Description
Alice and Bob now love to play a card game. Everyone is starting n cards, each card has no more than m attribute. Now they need finish Q tasks, each task will require everyone to give a card, and then make up the attribute types that the task demands (e.g. the task required attributes A, B, C, Alice’s card contains A B and Bob’s card contains B, C. they can use this union to finish the task).
For each task, How many ways that Alice and Bob can do this task.
Input
here are T cases. (T<=20) (about 5 test cases n>=1000 m>=12 Q>=1000)
For each test case.The first line contains two integers n,m(n<=100000, m<=18), which indicates the number of cards which each one has and total attributes.
The next line contain n binary numbers indicates the cards Alice has. The ith binary number m_i indicates the attributes each card have. (m_i <2^18)
(if m_i = 10011 , this card has the first, second and fifth attrtbutes)
The next line contain n binary numbers indicates the cards Bob has.
Then contain one integer Q which is the number of Tasks.
Then next Q lines, each contain one binary number q_i which indicates the attributes they need to make. (qi < 2^18)
Output
For each test case, you first output one line “Case #%d:”
Then output q lines, each line contains one which indicates the ways they can finish this task.
Sample Input
1 4 4 1001 11 1100 1000 1110 1001 10 100 2 1100 111
Sample Output
Case #1: 2 1
Hint
题意:应该就是二进制的或运算吧
思路:用普通的写法,怎么改都被T了,然后复制了标程的fwt.(快速沃尔什变换?我目前也不知道是什么,把问题留着吧)
#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=1<<18;
ll a[maxn],b[maxn];
char tmp[20];
// 快速沃尔什变换???????
void fwt(ll *A,int n){
for(int k=1;k<n;k<<=1){
int len=k<<1;
for(int j=0;j<n;j+=len){
for(int i=0;i<k;i++){
int x=A[i+j],y=A[i+j+k];
A[i+j+k]=x+y; //or
}
}
}
}
void ufwt(ll *A,int n){
for(int k=1;k<n;k<<=1){
int len=k<<1;
for(int j=0;j<n;j+=len){
for(int i=0;i<k;i++){
int x=A[i+j],y=A[i+j+k];
A[i+j+k]=y-x; // or
}
}
}
}
int main(){
int t,cas=0;scanf("%d",&t);
while(t--){
int n,m,q,len;scanf("%d%d",&n,&m);
int tot=1<<m;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<n;i++){
scanf("%s",tmp);
len=strlen(tmp);
int e=0;
for(int j=0;j<len;j++){
e<<=1;
e|=(tmp[j]-'0');
}
a[e]++;
// cout<<a[i]<<endl;
}
for(int i=0;i<n;i++){
scanf("%s",tmp);
len=strlen(tmp);
int e=0;
for(int j=0;j<len;j++){
e<<=1;
e|=(tmp[j]-'0');
}
b[e]++;
// cout<<b[i]<<endl;
}
fwt(a,tot); fwt(b,tot);
for (int i = 0; i < tot; i++) a[i] = a[i]*b[i];
ufwt(a,tot);
scanf("%d",&q);
cout<<"Case #"<<++cas<<":"<<endl;
while(q--){
int e=0;scanf("%s",tmp);
len=strlen(tmp);
for(int i=0;i<len;i++){
e<<=1;
e|=(tmp[i]-'0');
}
printf("%lld\n",a[e]);
}
}
}