HDU 5270 归并排序
来源:互联网 发布:java把两个数组合并 编辑:程序博客网 时间:2024/06/04 18:10
问题描述
ZYB喜欢研究Xor,现在他得到了两个长度为n 的数组A,B。于是他想知道:对于所有数对(i,j)(i∈[1,n],j∈[1,n]) ,(Ai+Bj) 的xor之和为多少定义多个数A1 ,A2 ...Ak 的xor 之和为A1xorA2xorA3xor...xorAk
输入描述
一共T (T≤10 )组数据,对于每组数据:第一行一个正整数n ,表示数组长度第二行n 个非负整数,第i 个整数为Ai 第三行n 个非负整数,第i 个整数为Bi n∈[1,105] ,Ai,Bi∈[0,260] 保证所有n 的和小于等于2∗105
输出描述
每组数据输出一行Case #x: ans。x表示组数编号,从1开始。ans为所求值。
输入样例
158 11 30 28 028 27 22 0 0
输出样例
Case #1: 34
1003 ZYB loves Xor II我们考虑两个数A ,B 。为了描述方便,我们设[P]的值为:当表达式P的值为真时,[P]=1,否则[P]=0我们现在考虑计算[(A+B)and(2i)>0] 首先我们将A,B都对2i+1 取模,显然这样是不会影响答案的则有一个十分显然的等式:[(A+B)and(2i)>0]=[(A+B)≥(2i)]−[(A+B)≥(2i+1)]+[(A+B)≥(3∗2i)] 这个式子相当容易理解,这里不多述了考虑每一位对答案的贡献是独立的,我们每一位分开做于是现在问题变成了:给定数组A,B ,求满足Ai+Bj≥limit 的数对个数我们可以将A,B 排序后,直接O(n) 计算即可然而排序是O(nlogn) 的,这样总复杂度就是O(nlognlogA) 了,无法通过此题于是这里有个小技巧我们从高位往低位做,现在我们要实现的是:将A 中每个数对P 取模后将A 排序我们发现A 会被分成两段,一段小于P ,一段大于等于P ,只有后面一段要取模,我们可以取模后直接将这两段归并,复杂度是O(n) 的时间复杂度:O(nlogA+nlogn)
此题注意位运算的大量使用,很省时间,而且容斥的想法和转化很巧妙。
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string.h>#include<vector>#include<algorithm>#define ll __int64#define maxn 110000using namespace std;vector<ll>q[2];ll x[maxn],y[maxn];ll bit[100];int n;ll solve()//我擦。。这个归并太吊了{ ll ans=0; for(ll i=0;i<62;i++) { ll tot=0; q[0].clear();q[1].clear(); for(ll j=1;j<=n;j++) q[(x[j]>>i)&1].push_back(x[j]); for(ll j=0;j<q[0].size();j++) x[++tot]=q[0][j]; for(ll j=0;j<q[1].size();j++) x[++tot]=q[1][j]; tot=0; q[0].clear();q[1].clear(); for(ll j=1;j<=n;j++) q[(y[j]>>i)&1].push_back(y[j]); for(ll j=0;j<q[0].size();j++) y[++tot]=q[0][j]; for(ll j=0;j<q[1].size();j++) y[++tot]=q[1][j]; ll len1=1,len2=1,len3=1; ll limit1=1ll<<i; ll limit2=1ll<<(i+1); ll all=(1ll<<(i+1))-1;///这里加1LL// cout<<all<<" all"<<endl; ll sum=0;// for(int i=1;i<=tot;i++) cout<<x[i]<<" ";// cout<<endl;// for(int i=1;i<=tot;i++) cout<<(x[i]&all)<<" ";// cout<<endl;// for(int i=1;i<=tot;i++) cout<<y[i]<<" ";// cout<<endl; for(ll i=n;i>=1;i--) { while((((x[i]&all)+(y[len1]&all))<limit1) && (len1<=n)) len1++;//这里多加几个() while((((x[i]&all)+(y[len2]&all))<limit2) && (len2<=n)) len2++; while(((x[i]&all)+(y[len3]&all)<limit1+limit2) && (len3<=n)) len3++;//cout<<(x[i]&all)<<" "<<(y[len3]&all)<<" "<<len3<<" "<<y[len3]<<" "<<(limit1+limit2)<<endl; sum+=n-(len1-1-len2+1+len3-1);// cout<<len1<<" "<<len2<<" "<<len3<<endl;// cout<<n-(len1-1-len2+1+len3-1)<<endl; }// cout<<sum<<" sum "<<i<<endl; if(sum&1) ans+=bit[i]; } return ans;}int main(){// freopen("1003.txt","r",stdin); int cas; scanf("%I64d",&cas); bit[0]=1; for(ll i=1;i<=61;i++) bit[i]=bit[i-1]*2; for(ll ca=1;ca<=cas;ca++) { scanf("%I64d",&n); for(ll i=1;i<=n;i++) scanf("%I64d",&x[i]); for(ll i=1;i<=n;i++) scanf("%I64d",&y[i]);// cout<<solve()<<endl; printf("Case #%I64d: %I64d\n",ca,solve()) ; }}
0 0
- HDU 5270 归并排序
- 归并排序 hdu 3743
- HDU 1040 归并排序
- hdu 3743 归并排序
- hdu 1394 归并排序
- 归并排序题目整理归并(hdu)
- hdu 4911 Inversion (归并排序)
- POJ 2299 && HDU 3743 归并排序
- HDU 1394 线段树 || 归并排序
- hdu 1394 Minimum Inversion Number_归并排序
- hdu 4911 归并排序求逆序数
- HDU 3743 Frosh Week (归并排序)
- HDU 3743 归并排序模板题
- HDU 4911 归并排序题目解析
- HDU 1379 DNA Sorting (水归并排序)
- Hdu 4911 Inversion(裸归并排序)
- HDU-1394(线段树|归并排序)
- hdu 4911 归并排序求逆序数
- 我的Android学习.入门小基础(一)
- 【java基础】——String类和基本数据类型包装类
- C语言函数调用约定
- msix中断分析
- linux网络编程之一-----多播(组播)编程
- HDU 5270 归并排序
- java + tomcat +mysql 中文乱码问题
- 【麦可网】Cocos2d-X跨平台游戏开发学习笔记---第六课: Cocos2D-X引擎框架1
- SGU146 The Runner
- java笔记21 常用API
- Linux中xargs命令的重要作用------顺便分享一次面试经历和一次实战经历
- 进程间通信(8) - 共享内存(posix)
- 数据库连接join
- 【C# WinForm】类似QQ靠近屏幕边缘缩放功能