1. 约瑟夫(环)问题。
见于:http://www.cnblogs.com/liyangguang1988/p/3620007.html
(数学推理部分开始)
2. 不用任何中间变量交换两个变量 a 和 b 的值。
方法1: 方法2:(适用整型)
a = a + b; a = a ^ b;
b = a - b; b = a ^ b;
a = a - b; a = a ^ b;
3. 不用加减乘除求两个整数的和。
求整数 a,b 的和:
步骤A:令 s = a ^ b,将所有位相加,有进位处置 0 (相当于舍弃进位相加)。—>步骤B
步骤B: 令 d = a & b,则求出所有进位,
若 d == 0,则无进位,返回 s;
若 d != 0,则返回(d << 1) + s 。即将所有进位左移一位,将问题化成 (d << 1) 与 s 求和的问题。可令 a = d << 1,b = s,—>步骤A。
例如:a = 5,b = 13 时:计算机内表示为,a =0101,b = 1101,
步骤A: s = a ^ b = (0101) ^ (1101) = 0 1000. —>步骤B
步骤B: d = a & b = (0101) & (1101) = 0101。 1,3 位有进位,d != 0,于是 a = s = 1000,b = d << 1 = 0101,—>步骤A2。
步骤A2: s = a ^ b = (1000) ^ (0101) = 1101。—>步骤B2
步骤B2: d = a & b = (1000) & (0101) = 0000。d == 0 ,无进位,返回 s = 1101. 即 13
(注:负数在计算机中用补码表示,但是负数之间也满足这种求和方法。正数与负数之间求和也适用于此方法)
代码:
/********** 注:超出边界时溢出 *************/ int add(int num1, int num2) { int sum = num1 ^ num2; while(num1 & num2) { num1 = (num1 & num2) << 1; num2 = sum; sum = num1 ^ num2; } return sum; } int main() { std::cout << add(0x7fffffff >> 1, (0x7fffffff >> 1)+1) << std::endl; return 0; }
结果:
4. 不用乘、除、取余运算实现两个 int 值相除。
code:
class Solution { public: int divide(int dividend, int divisor) { if(divisor == 0) return INT_MAX; bool signal = false; bool overflow = false; if(dividend < 0) { signal = !signal; if(dividend == INT_MIN) { overflow = true; dividend++; } dividend *= -1; } if(divisor < 0) { signal = !signal; if(divisor == INT_MIN) { if(overflow) return 1; else return 0; } divisor *= -1; } int result = 0; while(dividend >= divisor) { int x(divisor); int r(1); while(dividend-x >= x) { x += x; r += r; } dividend -= x; result += r; } if(overflow && dividend +1 == divisor) result++; return signal ? (-result) : result; } };
5. 找数组中单数问题
见于:http://www.cnblogs.com/liyangguang1988/p/3622257.html
6. ACM: 今天是星期一,再过 1^1+2^2+3^3+4^4+…+N^N天后是星期几?( 0 =< N <= 10亿)时间限制:2秒
原题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5272
base: 0 1 2 3 4 5 6
0 0
1 1
2 1 2 4 1
3 1 3 2 6 4 5 1
4 1 4 2 1
5 1 5 4 6 2 3 1
6 1 6 1
code:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 string day[] = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" }; 5 int base[7][7]; 6 int circle[7] = {1, 1, 3, 6, 3, 6, 2}; 7 8 inline void init() 9 { 10 for(int i = 1; i < 7; ++i) 11 { 12 int step = 1; 13 base[i][0] = step % 7; 14 for(int j = 1; j < 7; ++j) 15 { 16 step *= i; 17 base[i][j] = step % 7; 18 } 19 } 20 } 21 22 int main() 23 { 24 int N; 25 init(); 26 while(cin >> N) 27 { 28 int sum = 0; 29 N = N % 294; 30 while(N) 31 { 32 int t1 = N % 7; 33 int t2 = N % circle[t1]; 34 sum = (sum + base[t1][t2]) % 7; 35 --N; 36 } 37 cout << (day[sum]) << endl; 38 } 39 return 0; 40 }
附:n x n 的正方形中,有多少长方形? 答案: C(n+1, 2)2-n(n+1)(2n+1)/6 = n(3n+2)(n2-1)/12 .