【題解】2021.9.11 - zhengru IOI 七連測 Day3
阿新 • • 發佈:2021-10-06
\(\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; }