【题解】2021.9.11 - zhengru IOI 七连测 Day3

\(\color{Red}{How-great-the-day-is-!(Wrong)}\)

T1 斯诺克

思路

代码

T2 翻转

思路

代码

T3 数对

思路

  • 对于每一个 \(a_i\)\(b_j\) ,当且仅当 \(a_i \oplus 2^x=b_j \oplus 2^y\)\(x ≠ y\)

  • 于是,只需要对于每一个 \(a_i\) 算出 \(a_i \oplus 2^x\) 的值,然后找与其相等的 \(b_j\) 的值即可。

  • 需要注意的是,当 \(a_i=b_j\) 时,对于每个次幂都会统计一次答案,减去即可。

  • 另外,因为判断的只是相等,所以对于每个数对有两种异或方式,答案要除以二。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<utility>
#include<deque>
#include<ctime> 
#include<sstream>
#include<list>
#include<bitset> 
using namespace std; 
int na[100233],nb[100233],cna,cnb,n,m;
map<int,int> sam;
long long ans,pa[3000233],pb[3000233];
int main(){
	scanf("%d%d",&n,&m);
	for(register int i=1;i<=n;++i){
		scanf("%d",&na[i]);
		sam[na[i]]++;
		for(register int j=0;j<30;++j){
			pa[++cna]=na[i]^(1<<j);
		}
	}
	for(register int i=1;i<=m;++i){
		scanf("%d",&nb[i]);
		ans-=sam[nb[i]]*30;
		for(register int j=0;j<30;++j){
			pb[++cnb]=nb[i]^(1<<j);
		}
	}
	sort(pa+1,pa+cna+1);sort(pb+1,pb+cnb+1);
	for(register int i=1,l=1,r=1;i<=cna;++i){
		while(pb[l]<pa[i]&&l<=cnb) ++l;
		while(pb[r]<=pa[i]&&r<=cnb) ++r;
		if(pa[i]==pb[l]) ans+=(r-l);
	}
	printf("%lld\n",ans>>1);
	return 0;
}

T4 回文串

思路

代码

posted @ 2021-10-06 16:07  Binaries  阅读(46)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end