zoukankan      html  css  js  c++  java
  • zoj 3870 Team Formation

    题目大意:所给的一个数组中任意两个数异或值大于这个两个数,即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(最后求的值) 加上相应位置上的值

    举个例子:

    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[N], 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
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    转载一个好用的div弹出层插件
    asp.net 母版页使用方法
    visual studio 代码排版组合键
    模仿米折网商品图片自动翻页效果
    BinaryWriter 、BinaryReader在读写
    Java 8 Lambda 表达式
    IBeacon协议分析
    Centos配置jdk和tomcat环境
    apidoc 生成Restful web Api文档
    数组和链表的区别
  • 原文地址:https://www.cnblogs.com/qq2424260747/p/4738486.html
Copyright © 2011-2022 走看看