《審美的歷程》課上有n位學生,帥老師展示了m幅畫,其中有些是梵谷的作品,另外的都出自五歲小朋友之手。老師請同學們分辨哪些畫的作者是梵谷,但是老師自己並沒有答案,因為這些畫看上去都像是小朋友畫的……老師只想知道,有多少對同學給出的答案完全相反,這樣他就可以用這個資料去揭穿披著皇帝新衣的抽象藝術了(支援帥老師^_^)。
答案完全相反是指對每一幅畫的判斷都相反。
第一行兩個數n和m,表示學生數和圖畫數;
接下來是乙個n*m的01矩陣a:
如果aij=0,表示學生i覺得第j幅畫是小朋友畫的;
如果aij=1,表示學生i覺得第j幅畫是梵谷畫的。
輸出乙個數ans:表示有多少對同學的答案完全相反。
3 21 0
0 11 0
同學1和同學2的答案完全相反;
同學2和同學3的答案完全相反;
所以答案是2。
對於50%的資料:n<=1000;
對於80%的資料:n<=10000;
對於100%的資料:n<=50000,m<=20。
還有一點就是取反,取反符號是「~」,異或符號是「^」,每位按 1 異或也可以達到取反的目的。兩者的區別是,取反是所有位都取反,異或可以按位取反,比如:000111,只有後三位取反
這麼聽著是不是直接用 「~」 也沒有問題,於是我就試了一下,直接用 ~a[i] 算,但是結果是錯的,我???,輸出了一下兩個結果,我蒙了
這什麼鬼??這二進位制數鐵定不對啊,於是我又請教度娘(度娘是真好用啊),發現了這麼個問題:x 的按位取反結果為 -(x+1) ,也就是~1 = -2,這是為什麼呢
計算機內部在做數**算時(也就是計算機的0和1的運算),都是以補碼為標準的,也就是說,計算機中就一種碼那就是補碼,而現實社會中的編碼規則,例如原碼、反碼都是我們自定義的,為了和計算機中的補碼形成轉換關係。所以說在我們手工計算這類由計算機計算的01運算,要站在計算機的角度。因此首先就要將我們的原碼反碼什麼的全都先轉為補碼,再來計算。這樣才能使得正數和負數的表示統一起來。
1的補碼是它本身(正數的原、反、補碼都是它本身,負數的原碼最高為1開頭,反碼是最高符號位不變,其餘位在原碼的基礎上取反,補碼是在反碼的基礎上+1即可得到)
1的補碼:00000001
~1 (也就是1按位取反運算,下面涉及的是補碼運算):
00000001按位取反,這裡需要將原始01串完全反轉過來,不存在最高符號位的概念,取反結果為: 11111110
注意這裡的結果是用補碼表示的,畢竟這還是機器表示形式,轉化為自然語言的編碼,把結果轉化為原碼就是:
補碼-1轉為反碼: 11111110 - 1 = 11111101
反碼再取反轉為原碼:11111101 = 10000010
原碼轉為十進位制,答案就是-2
所以,在程式裡需要取反的時候,不管是全部取反還是選擇位取反,都要用異或,用 「 ~ 」 會出問題的。。。
正確**奉上
# include using namespace std;
int n, m;
int a[50005];
int ans[2000000];
// 圖畫的最大值是20所以,二進位制表示就有2^20=1048576種
int sum = 0;
int main()
ans[a[i]]++; //記錄每個答案的人數
} int mmax = (1<
for(int i=0;i
cout << sum/2 << endl;
return 0;
}
二進位制演算法
首先是6個二進位制的運算子 運算子 含義 描述 按位與 如果兩個相應的二進位制位都為1,則該位的結果值為1,否則為0 按位或 兩個相應的二進位制位中只要有乙個為1,該位的結果值為1 按位異或 若參加運算的兩個二進位制位值相同則為0,否則為1 取反 是一元運算子,用來對乙個二進位制數按位取反,即將0變...
java二進位制正數和負數取反
反碼 取反 按位取反 這3個概念是不一樣的。取反 0變1,1變0 反碼 正數的反碼是其本身,對於負數其符號位不變其它各位取反 0變1,1變0 按位取反 這將是下面要討論的。要弄懂這個運算子的計算方法,首先必須明白二進位制數在記憶體中的存放形式,二進位制數在記憶體中是以補碼的形式存放的。另外正數和負數...
藍橋杯演算法訓練 二進位制數
資源限制 時間限制 1.0s 記憶體限制 256.0mb 問題描述 給定l,r。統計 l,r 區間內的所有數在二進位制下包含的 1 的個數之和。如5的二進位制為101,包含2個 1 輸入格式 第一行包含2個數l,r 輸出格式 乙個數s,表示 l,r 區間內的所有數在二進位制下包含的 1 的個數之和。...