感想與收穫:
0x1
ACM蒟蒻選手
終於在專業課中
找到了ACM的感覺(躺)
0x2
就是不知道
能不能用
goto
和
遞歸
0x3
沒有 if 循環 減號的日子 想它
0x4
羨慕小建建
做了這麼多二進制
居然
還有頭髮
0x5
所以說
以後出題
出位運算和二進制
是會送命的
0x6
感謝
進制轉換在線工具
在我猜題意的時候
提供幫助
https://tool.lu/hexconvert/
0x7
做這種題,是不會感受到幸福的
************************************************************************************************
int lsbZero(int x) {
return x >> 1 << 1;
}
原來那個分數35是所有的得分合起來………而不是第一題的得分
各種姿勢都換了各種括號都加了還是 1 / 35偶爾還變成 0 / 35了真是傷心
放棄治療做了下一題
突然發現分數變成了 3 / 35……
浪費了一節課……
絕望
************************************************************************************************
int byteNot(int x, int n) {
return x ^ (255 << (n << 3));
}
要求固定byte求反(下標從 0 開始)
只需要構造出一個新的數字
在要求求反的byte區間都爲 1
其它地方都爲 0
再和原數據異或一下就好了
思路清晰
重點就在於怎麼構造上面所說的數字
一個byte長度爲 8
所以就先來一個2 ^ 8(全爲1),即255,再左移就好了
直接左移只能移動1
非常醜陋
所以我們先預處理出 n << 3
這樣一就能八個八個移動了
************************************************************************************************
int byteXor(int x, int y, int n) {
return!!((x & 255 << (n << 3)) >> (n << 3) ^ (y & 255<< (n << 3)) >> (n << 3));
}
int logicalAnd(int x, int y) {
return (!!x) & (!!y);
}
int logicalOr(int x, int y) {
return (!!x) | (!!y);
}
按照第二題的方法,把兩個數字的第 n 個byte取出來,所以用 &
這樣一來除了要求比較的地方其他地方都是0
取出來以後再異或一下就只剩下判 0 了
然後
‘!’ 號是個bug啊……
受到前面題的影響,下意識的以爲沒有O(1)的方法判斷一個數字是不是爲0
甚至想偷偷把函數返回值改成 bool型(小聲)
之前還在想符號給我個’!’有什麼用= =
被別人提醒了才發現可以有 “!!”這種操作。
可以把變量轉化成 bool 型
第三題切了第四第五也順理成章的寫了下來。
************************************************************************************************
int rotateLeft(int x, int n){
return(x << n) + ((x >> (32 + ~n + 1)) & ~((~0) << n))
}
題意感人
之前都是從右往左數
突然來了一個從左往右數
懵逼
看樣例和函數名枚舉題意
上一題把 ’!‘ 忘了喫虧了
這一題想着把‘~’個用上
然後就……
湊出來了欸……
分別取出低位和高位
再把其他部分都變成 0
加起來就好了
因爲不能用減號
所以需要利用補碼的原理模擬減法
************************************************************************************************
int parityCheck(int x) {
return (x = (x = (x = (x = (x = x ^ (x >> 16)) = (x ^ 8)) = x ^ 4)= x ^ 2) = x ^ 1) & 1;
}
關於異或很顯然的一個特點就是兩個數字異或不改變其 1 的個數的奇偶性
所以我們考慮用類似倍增的思想
先讓前半部分和後半部分異或
在用後半部分的前半部分和後半部分的後半部分異或
一次這樣操作
這樣一來最後一個數字就能代表所有數字的奇偶性
判斷一下是 1 還是 0 就OK 了
只是
感覺被針對了啊
明明本地都讓編譯
但是題目那邊就是不讓
強行提交假裝自己做出來了
************************************************************************************************
int mul2OK(int x) {
return (((x >> 31) & 1) + ((x>> 30) & 1) + 1) & 1;
}
因爲 *2也就相當於 <<
所以可能導致溢出的情況
也就是第 1 位和第 2 位(從左往右數,1開始計數)
數字相同
所以直接取出來
判斷是否相等就好了
這裏判斷是否相等的時候腦洞大了一點= =!
************************************************************************************************
int mult3div2(int x) {
return ((((x<< 1) + x) >> 1) + ((((x << 1) + x) & 1) & (((x<< 1) + x) >> 31) & 1));
}
剛開始以爲難點是怎麼算 *3
想到以後直接模擬
然後發現難點其實是負數的四捨五入的處理
剛開始不會做這個
然後做完了下面的取絕對值
突然有了靈感
到底要不要取整
取決於 *3 以後的奇偶性和符號
如果是奇數且爲負數
那就需要考慮人工取整
************************************************************************************************
int subOK(int x, int y) {
return ;
}
有了之前模擬減法的經驗
這題就很好做了
恩心裏這樣想這然後立了一個flag
然後沒做出來
************************************************************************************************
int absVal(int x) {
return!!(x & 1 << 31) + (x ^ (~(!!(x & 1 << 31))) + 1);
}
恩這個的難點在於負數怎麼處理
不允許用if
所以需要一個通用的方法
如果能想到通過正數和負數的符號位不同來設計就很好解決這個問題了(並不)
我們先考慮沒有運算次數限制的時候我們該怎麼做
正數取絕對值很簡單不要動就好了
負數則可以理解成帶上符號爲全部取反然後再+1S
直接取反肯定GG
因爲會影響正數
所以我們考慮異或的特性
對於負數 我們需要異或 1 再加 1 00101
於正數 我們需要異或 0 再加 0 11011
這樣 操作就同步了 00100+ 1
而且和符號位相關了!
接着考慮怎麼根據符號位 構造出全爲 1 或者全爲 0 的二進制數
首先想到的是倍增
通過 00000001 -> 00000011 -> 00001111-> 11111111
顯然操作數的限制不允許
然後在機緣巧合下
順手取了個反
然後發現再 + 1就好了
‘!!’真好用……
************************************************************************************************
unsigned float_abs(unsigned uf) {
if((uf & 2147483647) >2139095040){
return uf ;
}
else{
return uf & 2147483647;
}
}
能讓我用 if
一切都好說
然後
原來
不需要
一行
寫出來啊
************************************************************************************************
int float_f2i(unsigned uf) {
return0;
}
不會做
看了題解
原來
可以
聲明
變量啊
************************************************************************************************