这里是缅甸北部..
写傻了的D
复杂度:
思路正确,但实现实现的有点傻了
首先考虑 后恰好有两位是1,怎么用数学语言表示:
那么有:
那么很显然,只需要保证,然后求相等即可。
这样就可以先把一边用哈希存起来(被
掉了),遍历另一边所有的结果。
这时候得到的结果是包含 的,考虑
还满足上述式子:
相等成立的话
必然有:,所以减去
相等的方案数就好了。
最后方案数就是答案
这里其实不需要容斥,看rk1代码即可,思路是类似的。
Code:
/*** keep hungry and calm CoolGuang! ***/
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const ll maxn = 1e7+700;
const int M = 1e6+8;
const ll mod= 1e6+7;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
struct Hash{
int e,next,w;
}edge[maxn];
int head[maxn];
ll cnt=0;
map<ll,int>ca;
void Insert(int x){
ll temp=x%mod;
for(int i=head[temp];~i;i=edge[i].next){
if(edge[i].e==x){
edge[i].w++;
return;
}
}
edge[cnt]=Hash{x,head[temp],1};
head[temp]=cnt++;
}
ll Find(ll x){
ll temp=x%mod;
for(int i=head[temp];~i;i=edge[i].next){
if(edge[i].e==x) return edge[i].w;
}
return 0;
}
ll a[maxn],b[maxn];
int main(){
memset(head,-1,sizeof(head));
read(n);read(m);
for(int i=1;i<=n;i++){
read(a[i]);
ca[a[i]]++;
}
ll tmp = 0;
for(int i=1;i<=m;i++){
read(b[i]);
tmp += ca[b[i]]*30;
}
for(int i=1;i<=n;i++){
for(int k=0;k<30;k++)
Insert(a[i]^(1ll<<k));
}
ll ans = 0;
for(int i=1;i<=m;i++)
for(int k=0;k<30;k++)
ans += Find(b[i]^(1<<k));
dl((ans-tmp)/2);
return 0;
}

京公网安备 11010502036488号