這是一道很是基礎的題目,考察對位運算的理解,好看題目只以爲好眼熟,而後(手賤)瞟了一眼答案,第一遍沒看明白答案的內容,就上網查了一下,網上的人要麼就是一筆帶過(大概是以爲太簡單),要麼就是誤人子弟。html
解決題目以前應該先搞清楚題目是幹嗎的:ios
位向量顧名思義就是用位來存儲一個數,文中說存儲N=10000000個數,每一位表明一個數。數組
咱們能夠定義一個int類型的數組int a[N],那麼若是a[9]的值爲1,則代表文件中存在一個值爲9。函數
這樣的話,咱們就能夠用一個數組來表示這麼多數。咱們又知道,一個int型的數有4個字節,也就是32位,那麼咱們能夠用N/32個int型數來表示這N個數:測試
a[0]表示第1~32個數(0~31)spa
a[1]表示第33~64個數(32~63)設計
…code
這樣,每當輸入一個數字i,咱們應該先找到該數字在數組的第幾個元素中,也就是a[?],而後再肯定在這個元素的第幾位中。htm
舉個例子來講,好比輸入35,那麼35/32爲1餘3,則應該將a[1]的第4位置爲1。blog
好,有了上面的概念,能夠先來看看題中set是怎麼實現的:
void set(int i) { a[i>>SHIFT] |= (1<<(i &MASK)); }
根據題目的要求,咱們不能夠用/運算符來設計程序,那除的話咱們能夠用右移來替代:
m>>n,表示m往右移動n位
輸入i,除以32至關於往右移動5位,則i>>SHIFT表明i/32獲得應該放在數組的第幾個元素中,而後要置相應的位置位1了:
先來看看1<<(i&MASK)是什麼意思。i&MASK至關於取i右移掉的部分,說白了就是取餘數。
好比35的二進制表示是:… 0010 0011
MASK的二進制是0001 1111
兩個相與操做獲得0 0011
而右移5位,移掉的數是0 0011,換算成10進制是3,正是餘數,與上面的操做值相等,都是0 0011。
所以1<<(i&MASK)就變成了1<<3,也就是將1右移3位,變成了1000。
而後在作一個|操做就將a[1]的第4位置1了。
對於clr函數,就是找到位置,而後清零
對於test函數,就是找到位置,作一個與操做,若是存在這個數,則返回1,不存在的話,由於是&操做,因此返回0。
下面是全部的答案:
#define BITSPERWORD 32 #define SHIFT 5 #define MASK 0x1F #define N 10000000 int a[1+N/BITSPERWORD]; void set(int i) { a[i>>SHIFT] |= (1<<(i &MASK)); } void clr(int i ) { a[i>>SHIFT] &= ~(1<<(i &MASK)); } int test(int i ) {
能夠寫一個main函數測試一下:
#include <iostream>//不要忘記它 using namespace std;//不要忘記它 int main(){ int i = 35; //設置i,也就是置相應位置位1 set(i); //測試是否置1了 if(test(i)) cout<<"ok"<<endl; return 0; }
大概就這樣了。