1, 补码 = 反码 + 1 (求反码时保持符号位不变对余下所有位取反)
2, 补码表示如下: (以n位补码为例,约定:最低位为第0位)
(含n - 1个0) : 表示最小的负整数: -
(含n个1): 表示最大的负整数: - 1
(含n - 1个1): 表示最大的正整数:
3, 将n为整数S(对应C++中使用补码表示的整型)所有位取反对应~S, 则~S对应的原码数值为-1 - S,
4, 任意的运算数类型均为(unsigned int), 且只含有+(加), -(减),*(乘)的C++算术表达式的最终结果均为将其实际计算结果对取模(注意:这里指数学意义上的取模运算, 不同于C++中的%运算, 稍后将进一步说明), 例如对于unsigned int a = 1e10, unsigned b = 1e10, 则C++计算a * b - (a + b) 的结果为一个unsigned int型数值,该数值等于 , 如果将结论中的unsigned int 替换为unsigned long long则C++的计算结果是对于取模,下面给出这一结论的证明:
证明: 设s表示一个合法的,只含有+, -, *运算的, 所有操作数均为unsigned int(long, long long)类型的C++算术表达式, 定义s.len为s中所有运算符, 运算数和圆括号的总个数, 根据c++语法规则, 将一个整数(可以是负整数)p赋值给unsigned int型的变量a时, a被赋予的值为p mod ,因此当s.len为1时, 上述结论成立,
假设当s.len <= k, (k >= 1, 且k是s.len可以取到的一个合法值)时上述结论成立, 设t为s.len可以取到的且大于k的最小值, 则此情况下, s必定形如 () 或 l op r, 前者指s的最左端和最右端是一对相匹配的括号, 也即s中所有的运算符均位于某个括号之内, 后者指s中存在不在任何括号内部的运算符. 对于前者C++编译器会先计算括号内部的, 且, 因此为其实际值对取模, 对于后者C++编译器先计算子表达式l和r, 且l.len <= k, r.len <= k, 故l和r的计算结果均为其实际结果对取模, 又有op必为+, -, *之一,根据模运算性质, C++将l op r的结果对取模, 因此当s.len为t时上述结论成立, 故对任意s.len >= 1上述结论均正确,从而结论得证
5, C++ 常用数据类型及其范围和精度:
int 范围: [-0x80 00 00 00, 0x7f ff ff ff], 即 []-2 147 483 648, 2 147 483 647] (级别), 占用4个字节
unsigned int 范围: [0x00 00 00 00, 0xff ff ff ff], 即 [0, 4 294 967 295] (级别), 占用4个字节
long long 范围: [-9 223 372 036 854 775 808, 9 223 372 036 854 775 807] (级别), 占用8个字节
unsigned long long 范围: [0, 18446744073709551615] (级别), 占用8个字节
double 有效数字(十进制表示下的最高位, 去尾近似): 15 ~ 16位
long double 有效数字(十进制表示下的最高位, 去尾近似): 18 ~ 19位
对于int变量, 常用0x3f3f3f3f表示, 因为该数是集合{n | n * 2 <= 2 147 483 647且n(int型32位))的每个字节中的值相同} 中的最大正整数
同时使用语句memset(arr, 0x3f, sizeof(arr)), 可将int数组arr中每个元素的值设置为0x3f3f3f3f
6, 对于任意整型(不局限于int)的变量a(可以为负整数), 满足a << i = a * , (i >= 0, 且 a << i 0)
在将>>实现为算术右移(高位以符号位填充)的C++编译器中, 对于任意整型(不局限于int)的变量a(可以为负整数)有下述等式成立
a >> i 等于 (注意:此处"/"是指数学上的除法计算, 而不是C++中的除法运算符)
特别的, = 1 << i, a << 1 = a * 2, a >> 1 = (注意:此处"/"是指数学上的除法计算, 而不是C++中的除法运算符, 对于C++中的除法运算符计算两个整型变量a / b 的结果为将数学上a / b的结果向0取整, 同时对于C++中的%运算符满足: a % b 等于 a - (a / b) * b(此处的"/"作为C++中的除法运算符), 这也就时为什么C++中的%运算不同于数学上的模运算的原因.
7, 对于任意正整数m, 其在二进制表示下的位数为, (注意在计算机科学中lg表示以2为底的对数)
8, 设, 下面的&, |, ^ 为C++中的位与, 位或, 位异或运算符,则有:
a & 0 = 0, a & 1 = a (适用于将某些位置0, 其它位不变)
a | 0 = 1, a | 1 = 1 (适用于将某些位置1, 其它位不变)
a ^ 0 = a, a ^ 1 = 1 - a (适用于将某些位取反, 其它位不变)
9, 设n为非负整数, 定义lowbit(n)为n在二进制表示下由其"最低位的1及其后所有的0"构成的数值, 则有lowbit(n) = n & (-n), 证明从略.
在lowbit(n)定义的基础上可给出时间复杂度为二进制表示下n中1的个数线性函数的,用于计算a的二进制表示下1的个数的函数count(n)如下:
//返回非负整数n在其二进制表示下1的个数
int count(int n){
int ans = 0;
while(n) n -= n & ( -n), ++ans;
return ans;
}
10, 对于一定范围的非负整数k, 高效索引 lg的技巧: 两两不等, 且取遍1 ~ 36, 示例如下:
int hash[37];
//将2^0...2^35索引到数组hash, 其中lg(2^k) =hash[a^k % 37]
void hash(){
for(int i = 0; i <= 35; ++i) hash[(1ll << i) % 37] = i;
}
//返回lgk的值, 要求k为2的整数次幂且k <= 2^35
int getVal(long long k){
return hash[k % 37];
}
11, 模运算性质
(1), (a + b) mod p = (a mod p + b mod p) mod p
(2), (a - b) mod p = (a mod p - b mod p) mod p
(3), (a * b) mod p = ((a mod p) * (b mod p)) mod p
(4), mod p = mod p