ZOJ - 3870 Team Formation(异或)

题意:给定N个数,求这N个数中满足A ⊕ B > max{AB})的AB有多少对。(A,B是N中的某两个数)

分析:

1、异或,首先想到转化为二进制。

eg:110011(A)和 1(B)--------A中从右数第三个数是0,若某个数B(eg:110,101,111,……)从左向右数第三个数为1,那么两个异或一定满足A ⊕ B > max{AB})。

还有哪些数B能让A ⊕ B > max{AB})呢?

根据上述,同理,从右数第四个为1的数B也符合要求。

很容易想到,将N个数排序,对于A前面的数,二分统计在1000~1111和100~111中的数,这些数B都能使A ⊕ B > max{AB}),

不过,这太耗时间了~

2、试想,只要从右数第三个数是1的数都符合,那二进制位数为3的数当然满足从右数第三个数是1呀,因为没有前导0呀,eg:100,101,110,111

所以,只要预处理出N个数中二进制位数为3的数,个数为x,那么这些数与A一定能使能使A ⊕ B > max{AB})。

再扩展一下,A其实是满足从右数第三个数为0的一类数,我们预处理时也统计出来,个数为y,那么x*y就是对于二进制从右数第三位中满足要求的AB对数。

对于二进制中的每一位都是同理,最后求和即可。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
    if(fabs(a - b) < eps) return 0;
    return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 30 + 10;
const int MAXT = 10000 + 10;
using namespace std;
int w[MAXN];
int id[MAXN];
int main(){
    int T;
    scanf("%d", &T);
    while(T--){
        memset(w, 0, sizeof w);
        memset(id, 0, sizeof id);
        int n;
        scanf("%d", &n);
        while(n--){
            int x;
            scanf("%d", &x);
            int cnt = 1;
            while(x){
                if(x % 2 == 0) ++id[cnt];
                ++cnt;
                x >>= 1;
            }
            ++w[cnt - 1];
        }
        LL ans = 0;
        for(int i = 0; i < 32; ++i){
            ans += (LL)w[i] * id[i];
        }
        printf("%lld\n", ans);
    }
    return 0;
}

  

时间: 2024-11-03 22:22:58

ZOJ - 3870 Team Formation(异或)的相关文章

位运算 ZOJ 3870 Team Formation

题目传送门 1 /* 2 题意:找出符合 A^B > max (A, B) 的组数: 3 位运算:异或的性质,1^1=0, 1^0=1, 0^1=1, 0^0=0:与的性质:1^1=1, 1^0=0, 0^1=0, 0^0=0: 4 假设A < B,一定要满足B的最高位对应A的值是0,这样才可能>B(即0^1=1): 5 然后比赛时假设A的极限是类似0111111的情况,最后假设有误: 6 题解是先把每个数最高位(1)的位置统计个数,1<<4 的意思是 000010000:

ZOJ 3870 Team Formation(位运算)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5518 For an upcoming programming contest, Edward, the headmaster of Marjar University, is forming a two-man team from N students of his university. Edward knows the skill level of each s

ZOJ 3872 Beauty of Array&amp;&amp;ZOJ 3870 Team Formation

3872链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3872 题目大意:给你n个数,问所有的连续的子序列中的所有元素的和(子序列中有相同元素只计算一次)(n<100000). 即若序列为1  2  3,则组成1,2,3,1 2,2 3,1 2 3,和为20: 若序列为1 2 2,则组成1,2,2,1 2,2 2,1 2 2,和为13: 解题思路:求不重复的序列和很简单,关键是去重. 现在看一个序列: 3  4 

ZOJ 3870 Team Formation

题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3870 题解: 如果x xor y>max(x,y),那么就会有x和y的最高位不同(二进制表示),并且对于最高位小的那个数的最高位的位置,最高位大的那个数在相同的位置应为0. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespac

zoj 3870 Team Formation 位运算

//给n个数,找有多少队的两个数的异或值大于它们自己 //对于两个数中小的那个数的最高位在大的数中该位为0 //那么两个数异或所得的数比两个数大 //否则,这个数比大的数小 #include<cstdio> #include<cstring> #include<cstdio> #include<algorithm> using namespace std ; const int maxn = 100010; long long  map[40]; int a

ZOJ 3933 Team Formation

费用流裸体......比赛的时候少写了一句话....导致增加了很多无用的边一直在TLE #include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const int maxn=500+10; int n; int belong[maxn]; in

zoj 3933 Team Formation(最小费用流裸题)

1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 5 #include<string> 6 #include<algorithm> 7 #include<set> 8 #include<map> 9 #include<vector> 10 #include<stack> 11 #include<queue> 12 #

Team Formation 浙江省赛 (异或)

Team Formation 题意:在n个队伍种选择两个队伍,使 满足 (i.e. A ⊕ B > max{A, B}).   n<1e5   时间:2s 分析: 首先对每个队员的the skill level 做处理,用二进制表示时记录1出现的位置,用数组bit[]保存: 遍历元素,在二进制中出现0的位置时,bit数组中此处为1的二进制就可以存进来,计算所有和即可. # include<iostream> #include<cstdio> #include<cs

ZOJ3870 Team Formation

1 /** 2 Author: Oliver 3 ProblemId: ZOJ3870 Team Formation 4 */ 5 /* 6 思路 7 1.异或运算,使用^会爆,想到二进制: 8 2.我们可以试着从前往后模拟一位一位的^那么只要当前位结果变大便是: 9 3.一般我们如何利用二进制呢?既然要爆那我们就存1的位置: 10 4.问题是怎么存,如何用? 11 5.我之前想的是每个数的每位1都存,但是那样造成的重复计算还没想出怎么避免.看了一下别人的博客,再尝试把每位数的最高位1存起来.