您的位置:首页 > 其它

zoj 3870 Team Formation

2015-08-18 09:50 183 查看
题目大意:所给的一个数组中任意两个数异或值大于这个两个数,即i^j > max(i, j),问有多少个这样的异或

1^1 = 0, 0^0 = 0, 1^0 = 1, 0^1 = 1

如果x的最高位i位是1,y的位是0,且y比x大,i不是y的最高位,异或后这一位变成1,且yi位以前的1也可以保存,则异或后肯定比两个数的最大值还大

先把数组用快排从大到小排一下序, 再把每个数转分别换为二进制,在二进制中是 0 的就在相应的位置加 1, 另外如果首位是 1 的话,就把 ans(最后求的值) 加上相应位置上的值

举个例子:

5

1 2 3 4 5

快排后是: 5 4 3 2 1

对应的二进制是:

0 0 0 0

1 0 1 b[1]++;

1 0 0 b[1]++, b[0]++;

1 1 ans+= b[1];

1 0 b[0]++, ans+= b[1];

1 ans+= b[0];

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100010

int ans, a
, b[110], c[110];//注意b,c的数组不能开太大,否则TLE(开始为图省事直接用N,直接TLE)

int cmp(const void *a, const void *b)
{
return *(int *)b - *(int *)a;
}

void slove(int n)
{
int i, j = 0;
memset(c, 0, sizeof(c));
while(n)
{
c[j++] = n % 2;
n /= 2;
}//将n转化成二进制
if(c[j - 1])//如果最高位是1与0异或其值必然大于这两个数,所以ans直接加上相应位置的值
ans += b[j - 1];
for(i = 0 ; i < j ; i++)
if(!c[i])
b[i]++;//c中等待1异或的0元素个加1
}

int main()
{
int n, t, i;
scanf("%d", &t);
while(t--)
{
ans = 0;
memset(b, 0, sizeof(b));
scanf("%d", &n);
for(i = 0 ; i < n ; i++)
scanf("%d", &a[i]);
qsort(a, n, sizeof(a[0]), cmp);
for(i = 0 ; i < n ; i++)
slove(a[i]);
printf("%d\n", ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: