zoukankan      html  css  js  c++  java
  • 【位运算】大吉大利

    大吉大利

    给定(n)个整数,依次为(a_1,a_2,...,a_n。)

    (sum_{i=1}^nsum_{j=1}^n(a_i&a_j))(&)是二进制的与运算符

    容易想到二重循环

    for(int i=1;i<=n;i++)
    	for(int j=1;j<=n;j++)
    		ans+=(a[i]&a[j]);
    

    时间复杂度为(O(n^2)),又(n<=10^5),超时了。

    考虑与运算的性质:是将每个数字转化成二进制数,再一位一位作计算的。只有当两个数都为1时结果才为1,其它情况结果均为0。

    以样例为例,5个数字化为二进制数得到

    (00001)

    (00010)

    (00011)

    (00100)

    (00101)

    对于最右边一列,在(a[1])与其它数(包括它本身)进行与运算时,这一列所得结果之和为3。(a[3])(a[5])时的情况同理。故这一列在求和过程中的总结果为9。即这一列中1的数目的平方。

    根据上述规律,继续计算其它列,最终得到的一串数字即所求和的二进制表示。

    注意,将所求和的二进制数转化为十进制时,因为返回值可能需要long long储存,所以不能用math.h里的pow函数(返回类型为double),要重新写一个。

    $color{green}{查看代码}$
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    
    long long a[1005], ans = 0;
    long long pow(int base, int n)
    {
        long long sum=1;
        while (n)
        {
            if (n&1) sum = base*sum;
            base *= base;
            n >>= 1;
        }
        return sum;
    }
    
    int main() {
        long long n, maxc = 0;
        cin >> n;
        for (int i = 1;i <= n;i++) {
            long long num, cnt = 0, nm;
            cin >> num;
            while (num) {//数num的二进制数中有几位是1
                if (num & 1) a[cnt]++;
                //num&1不为0,说明num的二进制数中的最右边那位是1
                //a[cnt]++表示计数第cnt列的1的个数
                cnt++;
                num >>= 1;
                //相当于num/=2
                //num二进制数右移1位
            }
            maxc = max(maxc, cnt);
            //更新最长的二进制数的长度 
        }
        for (int i = 0;i < maxc;i++)
            ans += a[i] * a[i] * pow(2, i);
        cout << ans;
        return 0;
    }
    
  • 相关阅读:
    利用DTrace实时检测MySQl
    改进MySQL Order By Rand()的低效率
    RDS for MySQL查询缓存 (Query Cache) 的设置和使用
    RDS For MySQL 字符集相关说明
    RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码
    RDS for MySQL Mysqldump 常见问题和处理
    RDS for MySQL Online DDL 使用
    RDS MySQL 表上 Metadata lock 的产生和处理
    RDS for MySQL 如何使用 Percona Toolkit
    北京已成为投融资诈骗重灾区:存好骗子公司黑名单,谨防上当!
  • 原文地址:https://www.cnblogs.com/streamazure/p/12585153.html
Copyright © 2011-2022 走看看