【位操作】大吉大利

2023-11-11 23:30
文章标签 位操作 大吉大利

本文主要是介绍【位操作】大吉大利,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://ac.nowcoder.com/acm/contest/4853/A

比赛思路:

感觉没有思路,感觉挺无奈的,没有发现其中的奥秘。

确实是一道想通了就不难的题目。比赛的时候应该把所有的二进制显示都列出来看一下的,说不定能发现规律。

只会暴力的思路:

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

但是一看数据范围就知道这样肯定是行不通的,至少也要O(nlogn)的算法~哎

题解:

光想是想不出来,不如列出来看一下?

比如说有5个数字,只看他们的末位:

1

0

1

0

1

并运算的规则是:有0出0,全1出1,所以一定要一对里两个同时为1才行。

按照题目的规则,则

则可以知道该位 1 的个数的平方,也就是该列两两互相&再相加的结果

每次列都这么操作,同时因为要将二进制转换为十进制,所有每次算出来的值还要乘上2的次方,

就像这里因为是最后一位,所以是 3^{2} * 2^{0} 。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,a[100005];
ll ans,cnt,nw;int read(){int x=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();return x;
}int main(){n=read();for(int i=1;i<=n;i++) a[i]=read();for(int i=27;i>=0;i--){cnt=0,nw=1ll<<i;//当前位为1,后面的位都为0;for(int j=1;j<=n;j++) if((a[j]&nw)) cnt++;//数这一位有几个1ans+=nw*cnt*cnt;}printf("%lld\n",ans);return 0;
}

这样的速度是很快的,

这里再放上另一种,方便理解

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005], ans=0;ll pow(int base, int n){//快速幂ll sum=1;while (n){if (n&1) sum = base*sum;base *= base;n >>= 1;}return sum;
}int main(){ll n, maxc=0; scanf("%lld", &n);for (int i=1; i<=n; i++){ll num, cnt=0, nm; scanf("%lld", &num);while (num){if (num&1) a[cnt] ++;cnt++;num >>= 1;}maxc = max(maxc, cnt);}for (int i=0; i<maxc; i++) ans += a[i]*a[i]*pow(2, i);printf("%lld", ans);
}​

 

这篇关于【位操作】大吉大利的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/393543

相关文章

位操作(Bitwise Operation)

位操作(Bitwise Operation)是一种直接对整数的二进制位进行操作的计算方法。在计算机中,数据通常以二进制形式存储,位操作允许我们直接操作这些二进制位。位操作通常比常规的算术运算更高效,因为它们直接作用于二进制位而不涉及更复杂的计算。 常见的位操作符 1.按位与(&): 对应位都为1时,结果为1,否则为0。 例如:1010 & 1100 = 1000 2.按位或(|): 只要对应

关于位结构体及位操作总结

#include <stdio.h>#pragma pack(1)struct stu{char a:4; // a占用char的低4位 char b:4; // b占用char的高4位(注意,这里实际上是与a共享同一个char的空间) };#pragma pack(4)int main(){struct stu s={.a=2, //a:0010.b=3, //b:00

使用位操作高效解决单个元素出现问题【位运算】

使用位操作高效解决单个元素出现问题 在日常的算法面试和编程挑战中,常常会遇到寻找单个出现元素的问题。尽管可以用哈希表(map)轻松解决,但要求更高效的线性时间复杂度和常量空间复杂度时,位操作特别是异或(XOR)运算提供了一个巧妙的解决方案。本篇博客将深入探讨这个问题,详细解释异或运算的特性,并展示其在解决该类问题中的强大作用。 问题描述: 给定一个非空整数数组,除了某个元素只出现一次以外,其

AWTK fscript 中的位操作扩展函数

fscript 是 AWTK 内置的脚本引擎,开发者可以在 UI XML 文件中直接嵌入 fscript 脚本,提高开发效率。本文介绍一下 fscript 中的 位操作扩展函数 位操作扩展函数 1. & 位与运算。 原型 n1 & n2 示例 print(1 & 1) 2. | 位或运算。 原型 n1 | n2 示例 print(|(1, 2))

【Rust光年纪】深度剖析:Rust库探秘,从位操作到全文搜索

从位操作到全文搜索:探索Rust编程世界的精华库 前言 Rust作为一门现代化、安全性高的系统编程语言,拥有丰富多样的库和工具生态系统。本文将重点介绍几个在Rust语言中广受欢迎的库,它们分别用于处理位标志、位数组、布隆过滤器、Roaring Bitmaps、嵌入式数据库和全文搜索引擎功能。 欢迎订阅专栏:Rust光年纪 文章目录 从位操作到全文搜索:探索Rust编程世界的精

位操作实现加减乘除四则运算

常见的位操作实现 1. 常用的一个等式:-n = ~(n - 1) = ~n + 1 2. 获取整数的二进制的最右边的1:n & (-n) 或 n & ~(n - 1)。例如 n = 010100, -n = 101100,那么n & (-n) = 000100 3. 去除整数的二进制的最右边的1:n & (n - 1)。例如 n = 010100,n-1 = 010011,n&(n-1)

【位操作笔记】计算整数的绝对值 3

计算整数的绝对值(integer absolute) 3 用于计算整数的绝对值,不使用分支判断。 算法说明 CPU表示有符号数的是使用补码(two’s complement),正数的补码与原码相同;负数的补码,符号位为1,其余位对原码取反加1。 如果CPU表示有符号数使用的是反码(one’s complement),则该算法无效。 因为是使用补码(two’s complement),所以

【位操作笔记】计算整数的绝对值 2

计算整数的绝对值(integer absolute) 2 用于计算整数的绝对值,不使用分支判断。 算法说明 该算法利用CPU表示有符号数的是使用补码(two’s complement),正数的补码与原码相同;负数的补码,符号位为1,其余位对原码取反加1。 如果CPU表示有符号数使用的是反码(one’s complement),则该算法无效。 因为是使用补码(two’s complemen

【位操作笔记】判断两个整数的符号位是否相反

判断两个整数的符号位是否相反 判断两个整数的符号位是否相反,也就是两个数是否一个是正数,一个是负数。 算法说明 该算法通过异或的结果大小来判断两个整数的符号位是否相反。 实现代码 bool Detect_opposite_signs(int x, int y){return ((x ^ y) < 0);} 算法计算过程 第一步,x ^ y,两个整数先进行异或。 第二步,判断异