感想与收获:
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;
}
不会做
看了题解
原来
可以
声明
变量啊
************************************************************************************************