题意:
给出n个数,问做多可以找到多少对数字A,B,使得A xor B > max(A,B)。
思路:
感谢mzjj教本弱智。
对于一个数,只考虑小于它的数字。
假设对于一个数字x 11001001,对于从最高位开始的连续的1,满足条件的数y的这位一定不能为1,从碰到的第一位0开始:这一位就可以是1,后面无论是什么都可以满足条件;
如果这位不为1,那么直到碰到下一个0之前,都不能是1。
所以可以从小到大枚举,按最高位分组,对于当前来到的x,枚举它的0的位有多少,答案加上以这位为最高位的数字的个数。
然后把这个数字加进分组中。
一开始把b数组只开了10,以为10的9次方最多10位,确实是,但是那是10进制,二进制就是32位了,睿智了Orz。
我的代码:
1 #include2 #include 3 #include 4 using namespace std; 5 const int N = 1e5 + 10; 6 int a[N]; 7 int b[35]; 8 int main() 9 {10 int t;11 scanf("%d",&t);12 while (t--)13 {14 memset(b,0,sizeof(b));15 int n;16 scanf("%d",&n);17 for (int i = 0;i < n;i++)18 {19 scanf("%d",&a[i]);20 }21 sort(a,a+n);22 long long ans = 0;23 for (int i = 0;i < n;i++)24 {25 int x = a[i];26 int cnt = 0;27 while (x)28 {29 if (!(x & 1)) ans += b[cnt];30 cnt++;31 x >>= 1;32 }33 if (cnt == 0) continue;34 b[cnt-1]++;35 }36 printf("%lld\n",ans);37 } 38 return 0;39 }
学长的代码:
1 #include2 using namespace std; 3 typedef long long LL; 4 const int N = 1e5 + 5; 5 int T, n; 6 int a[N]; 7 int cnt[33]; 8 9 int main() {10 scanf("%d", &T);11 while(T--) {12 scanf("%d", &n);13 for(int i = 0; i < n; i++) {14 scanf("%d", &a[i]);15 }16 sort(a, a+n);17 memset(cnt, 0, sizeof(cnt));18 LL ans = 0;19 for(int i = 0; i < n; i++) {20 int x = a[i];21 int b = 31 - __builtin_clz(x);//返回左起第一个‘1’之前0的个数。22 for(int j = 0; j < b; j++) {23 if(~x&(1<