题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5518
题意就是有n个数,如果满足a^b > MAX(a, b),就算一种组合,问n个数之间这样的组合有多少个;
可以发现,如果要让一个数增大,只要该数化为二进制后的出现0的位置跟1异或就会变大,
同时需要满足另一个数的最高位为该数出现0位置的位数,
如10可以跟1异或变为11 ,100可以跟10、11、1异或分别变为110,111,101,而101只能跟两位的进行异或,
因为它的0出现的位置为第二位,最后求和就行了。
cnt[i]代表a数组都转换成二进制数后最高位所在位置i为1的数的个数;
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cstdlib> using namespace std; #define N 100010 int a[N]; int main() { int T, b[55], cnt[55], ans, n; scanf("%d", &T); while(T--) { memset(a, 0, sizeof(a)); memset(cnt, 0, sizeof(cnt)); scanf("%d", &n); for(int i=0; i<n; i++) scanf("%d", &a[i]); sort(a, a+n); ans=0; for(int i=0; i<n; i++) { int j=0; while(a[i]) { b[j++] = a[i]%2; a[i]/=2; } for(int k=0; k<j; k++) { if(b[k]==0) ans+=cnt[k];///表示首位是这个位置的并且为1的,0与之异或一定变大; } cnt[j-1]++;///让该位置为1的个数加1; } printf("%d ", ans); } return 0; }