基礎演算法題——異或和之和(位運算、組合數)
異或和之和
解題思路
解題方案
暴力列舉:時間複雜度:O(n3),超時。
位操作+組合數:解鈴還須繫鈴人。對於這種與、或、異或的位操作,一般也是通過位操作來解答。
總結規律
題目要求在 n 個正整數中列舉 3 個數進行位操作,若要確定 3 個數的異或結果,就要尋找對異或結果的位有影響的情況。
列舉可能情況:
0 ^ 0 ^ 0 = 0
0 ^ 0 ^ 1 = 1
0 ^ 1 ^ 0 = 1
0 ^ 1 ^ 1 = 0
1 ^ 0 ^ 0 = 1
1 ^ 0 ^ 1 = 0
1 ^ 1 ^ 0 = 0
1 ^ 1 ^ 1 = 1
①、當 3 個都為 1 時,異或的結果為 1 。
②、當 2 個為 0 時,異或結果為 1 。
③、除了 ①、② 外,其餘情況為 0 。
程式碼解析
①、列舉每一位二進位制數的值,先對 mod 求餘防止溢位。
eg:1(1), 2(10), 4(100), 8(1000)…
f[0]=1;
for(int i=1; i<64; i++)
f[i] = (f[i-1]<<1)%mod;
②、統計 n 個整數的每一位 1 的個數及 0 的個數。
0 的個數 = n - 1 的個數。可以不必再求。
//統計 n 個整數每一位為 1 的數量
//eg:num[j]: n 個整數第 j 位為 1 的數量
for(int i=0; i<n; i++){
ll tmp;
scanf("%lld", &tmp);
for(int j=0; j<64; j++)
num_1[j] += (tmp>>j)&1;
}
③、計算出每一位異或和結果能夠得到多少個 1 ( k ) ,最後將答案與該位大小 * 1 的個數( f [ i ] * k ) 累加起來,並求餘。
for(int i=0; i<64; i++){
ll one=num_1[i], zero=n-num_1[i], k;
//1 0 0 | 0 1 0 | 0 0 1
if(zero>=2 && one>=1){
k = zero*(zero-1)*one/2%mod;
ans = (ans+k*f[i]%mod)%mod;
}
//1 1 1
if(one>=3){
k = one*(one-1)*(one-2)/6%mod;
ans = (ans+k*f[i]%mod)%mod;
}
}
注意優先順序 :
‘*’、’/’ > ‘+’、’-’ > ‘%’ > ‘<<’、’>>’ > ‘=’
實現程式碼
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll ans=0;
int f[64]={0}, num_1[64]={0};
const int mod = 1e9+7;
int main(){
int n;
scanf("%d", &n);
f[0]=1;
for(int i=1; i<64; i++)
f[i] = (f[i-1]<<1)%mod;
//<<優先順序小於 mod
for(int i=0; i<n; i++){
ll tmp;
scanf("%lld", &tmp);
for(int j=0; j<64; j++)
num_1[j] += (tmp>>j)&1;
}
for(int i=0; i<64; i++){
ll one=num_1[i], zero=n-num_1[i], k;
//0 0 1
if(zero>=2 && one>=1){
k = zero*(zero-1)*one/2%mod;
ans = (ans+k*f[i]%mod)%mod;
}
//1 1 1
if(one>=3){
k = one*(one-1)*(one-2)/6%mod;
ans = (ans+k*f[i]%mod)%mod;
}
}
//優先順序 :
//'*'、'/' > '+'、'-' > '%' > '<<'、'>>' > '='
printf("%lld", ans);
return 0;
}
總結
位操作對於異或、與、或等位運算是十分有效的。
相關文章
- 位運算-異或(^)
- 計算機基礎:位運算計算機
- JAVA基礎提高之位運算Java
- 異或運算 XOR 教程
- JavaScript ^ 按位異或運算子JavaScript
- 演算法學習筆記(16): 組合數學基礎演算法筆記
- Java 基礎 之 算數運算子Java
- 或與運算和安全整數(數的影子)
- 演算法題:三數之和演算法
- 深入理解按位異或運算子
- 【刷題1】LeetCode 39. 組合總和 java基礎LeetCodeJava
- 演算法之位運算演算法
- 【每日演算法】位運算演算法
- 【演算法】位運算技巧演算法
- python系列--計算異或和Python
- Python基礎學習篇-2-數值運算和字串Python字串
- 洛谷題單指南-數學基礎問題-P2822 [NOIP2016 提高組] 組合數問題
- 演算法之美 : 位運算演算法
- 挑戰演算法題:四數之和演算法
- Java程式設計基礎03——進位制運算&資料型別&變數Java程式設計資料型別變數
- 【Java資料結構與演算法】簡單排序、二分查詢和異或運算Java資料結構演算法排序
- 4、python基礎運算和流程控制Python
- 分組異或
- 1的個數 【位運算】
- Python基礎運算分享Python
- 3.2 Tensorflow基礎運算
- Oracle分割槽表基礎運維-05組合分割槽Oracle運維
- 位運算實現整數與位元組陣列轉換陣列
- 位運算的操作與演算法演算法
- Java基礎06 組合Java
- 在C#中對列舉進行位運算--列舉組合C#
- 基礎拾遺:除了&和&&的區別,你還要知道位運算的這5個運算子
- 【演算法技巧】位運算裝逼指南 ---- 帶你領略位運算的魅力演算法
- 【演算法】GPLT - 基礎梯級練習題 - 個位數統計(15分)演算法
- 組合數問題
- js運算元組中資料排列組合JS
- 演算法競賽進階指南 - 位運算3題詳解演算法
- 演算法之字首樹——最大異或和演算法