arc 092D Two Sequences

题意:

给出两个长度N相同的整数序列A和B,有N^2种方式从A中选择一个数Ai,从B中选择一个数Bj,让两个数相加,求这N^2个数的XOR,即异或。

思路:

暴力的求显然是会超时的,因为是异或,就考虑在最后的结果中以二进制表示每一位是0还是1。

在计算第i位是否为1的时候,显然不需要考虑更高位的影响,那么假设T = 2 ^ i,就将A和B中的每一个数对2T求余。

然后,只有以下两种情况可以满足第i位为1:

T <= Ai + Bj < 2T;

3T <= Ai + Bj < 4T.

将B排序之后,对于每一个Ai,第一种情况和第二种情况,都可以找到Bj对应的区间,善用lower_bound。如果两个区间长度加起来为奇数,那么这一位就是1。

一定用long long。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 
 7 const int N = 200005;
 8 
 9 long long a[N],b[N];
10 long long c[N],d[N];
11 
12 bool f[35];
13 
14 int main()
15 {
16     int n;
17     
18     scanf("%d",&n);
19     
20     for (int i = 0;i < n;i++)
21     {
22         scanf("%lld",&a[i]);
23     }
24     
25     for (int i = 0;i < n;i++)
26     {
27         scanf("%lld",&b[i]);
28     }
29     
30     for (int i = 0;i <= 30;i++)
31     {
32         long long t = ((long long)1 << i);
33         
34         for (int j = 0;j < n;j++)
35         {
36             c[j] = a[j] % (2 * t);
37             d[j] = b[j] % (2 * t);
38         }
39         
40         sort(d,d+n);
41         
42         for (int j = 0;j < n;j++)
43         {
44             long long y = 2 * t - c[j];
45             long long x = t - c[j];
46             
47             int p1 = lower_bound(d,d+n,x) - d;
48             int p2 = lower_bound(d,d+n,y) - d;
49             
50             if (d[p2] >= y) p2--;
51             if (p2 >= n) p2--;
52             //if (p1 >= n) p1--;
53             
54             if (p2 >= p1 && (p2 - p1 + 1) % 2) f[i] = !f[i];
55             
56             y = 4 * t - c[j];
57             x = 3 * t - c[j];
58             
59             p1 = lower_bound(d,d+n,x) - d;
60             p2 = lower_bound(d,d+n,y) - d;
61             
62             if (d[p2] >= y) p2--;
63             if (p2 >= n) p2--;
64             //if (p1 >= n) p1--;
65             
66             if (p2 >= p1 && (p2 - p1 + 1) % 2) f[i] = !f[i];
67         }
68     }
69     
70     long long ans = 0;
71     
72     for (int i = 0;i <= 30;i++)
73     {
74         if (f[i]) ans |= ((long long)1 << i);
75     }
76     
77     printf("%lld\n",ans);
78     
79     return 0;
80 }

 

转载于:https://www.cnblogs.com/kickit/p/8809546.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值