描述
衆所周知的(什麼?你不知道?去百度一下),Nobody的團舞裏有一個經典動作(那是相當的經典,經典了好幾年),而這個動作是對稱做兩遍的.蔥歌很喜歡這個動作(Mikuer們不要BS我…),她很想多做這個動作.
但是邪惡的F,爲了少看這無語的動作,給了蔥歌兩排非負整數.一排A數,一排B數.A數有n個,B數有m個.如果一個A數和一個B數的二進制表示法中,每一位都不一樣的話(不足的數高位補0),則A和B能夠組成一個”對稱音”.每個數只能屬於一個”對稱音”.蔥歌想要最多的對稱音,讓她可以儘量多跳那個動作.
格式
輸入格式
輸入共3行.
第1行兩個正整數n,m,表示A數n個,B數m個.
第2行n個非負整數,表示n個A數.
第3行m個非負整數,表示m個B數.
輸出格式
一行一個正整數,表示最多能得到的”對稱音”個數.如果一個對稱音都得不到,輸出”I want nobody nobody but you”.
代碼
關鍵在位運算… 剩下的就是匈牙利算法模板。
#include <cstdio>
#include <cstring>
#include <cmath>
#define INF 0x3f
#define maxn 400
using namespace std;
int n,m,a[maxn],b[maxn],ans=0;
bool w[maxn][maxn],vis[maxn];
int match[maxn];
bool judge(long long x)
{
x++;
for(long long i=1;i<=x;i=(i<<1)) if(i==x) return 1;
return 0;
}
bool find(int x){
for(int i=1;i<=m;i++){
if(w[x][i]&&!vis[i]){
vis[i]=true;
if(match[i]==-1||find(match[i])){
match[i]=x;
return true;
}
}
}
return false;
}
int main(){
freopen("in.txt","r",stdin);
memset(w,0,sizeof(w));
memset(match,-1,sizeof(match));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if (judge(a[i]+b[j])) w[i][j]=true;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(find(i)) ans++;
}
if(ans!=0) printf("%d",ans);
else printf("I want nobody nobody but you");
return 0;
}