1094: 有多少位是1
題目連結:http://oj.ecustacm.cn/problem.php?id=1094
時間限制: 1 Sec 記憶體限制: 256 MB
題目描述
把一個正數轉成二進位制數後,各位數字分別是0或1,請你程式設計統計有多少位是1。
如11的二進位制數是1011,共有三位是1。
輸入
輸入有若干行,每行一個正整數,數字不超過10^18。
輸出
對應輸出二進位制數的1的個數。
樣例輸入 Copy
11
1
721
樣例輸出 Copy
3
1
5
來源/分類
基礎題 數論
題意:就是求一個二進位制數有多少個一
思路:用簡單好理解的直接轉為二進位制統計一的個數,或者用與運算來做。以下提供三種題解。
法一: 將原數字轉為二進位制,在此過程統計1的個數
這個方法不用多說,就是轉換過程中多加個判斷語句統計下即可
程式碼:
1 num=0; 2 long long m=n; // 法一: 將原數字轉為二進位制,在此過程統計1的個數 3 while(m!=0) 4 { 5 int t=m%2; 6 if(t==1) 7 num++; 8 m/=2; 9 } 10 cout<<num<<endl;
法二: 將原數字(二進位制)一直往右移動 與 1 進行 與運算
舉個例子,比如數字5,二進位制表示為101(忽略前面的0),
101往不斷右移,每次都與1進行與運算,如果結果等於1就說明存在一個1,直到移動64位後停止(因為題目給的數量級是:數字不超過10^18,所以用long long)然後統計個數就可以了
101(原數字,也就是右移0位後的數字)
001(1)
001 相與的結果等於1(num++)
---------------------------------------------------------
010 (右移1位後的數字)
001(1)
000 相與的結果不等於1
---------------------------------------------------------
001 (右移2位後的數字)
001 (1)
001 相與的結果等於1(num++)
---------------------------------------------------------
001再右移就變成000了(所以到這也就把所有的1統計完了)
000 (右移3位後的數字)
001 (1)
000 相與的結果不等於1
程式碼:
1 num=0; 2 for(int i=0; i<64; i++) // 法二: 將原數字(二進位制)一直往右移動 與 1 進行 與運算 3 { 4 if(((n>>i)&1)==1) 5 num++; 6 } 7 cout<<num<<endl;
法三: 每次消掉最後面的那個1
這個很巧妙,就是讓n=((n-1)&n),直到n==0停止,這個過程中每次就可以消掉最右邊的那個1
還用5舉例 101
101 (n)
100 (n-1)
100 相與的結果等於100,沒跳出迴圈num++
然後n=100了
---------------------------------------------------------
100 (n)
011 (n-1)
000 相與的結果等於100,此時還沒跳出迴圈num++
n=0了,跳出迴圈了,結束。
程式碼:
1 num=0; 2 while(n!=0) // 法三: 每次消掉最後面的那個1 3 { 4 n=((n-1)&n); 5 num++; 6 } 7 cout<<num<<endl;
完整程式碼:
1 #pragma GCC optimize(2) 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<map> 8 #include<stack> 9 #include<set> 10 #include<vector> 11 #include<queue> 12 #include<iomanip> 13 #include<bitset> 14 using namespace std; 15 int main() 16 { 17 long long n,x; 18 long long num=0; 19 while(cin>>n) 20 { 21 num=0; 22 long long m=n; // 法一: 將原數字轉為二進位制,在此過程統計1的個數 23 while(m!=0) 24 { 25 int t=m%2; 26 if(t==1) 27 num++; 28 m/=2; 29 } 30 cout<<num<<endl; 31 32 num=0; 33 for(int i=0; i<64; i++) // 法二: 將原數字(二進位制)一直往右移動 與 1 進行 與運算 34 { 35 if(((n>>i)&1)==1) 36 num++; 37 } 38 cout<<num<<endl; 39 40 num=0; 41 while(n!=0) // 法三: 每次消掉最後面的那個1 42 { 43 n=((n-1)&n); 44 num++; 45 } 46 cout<<num<<endl; 47 48 } 49 return 0; 50 }
任取一種方法即可
加油!
共同努力!
Keafmd