TopCoder - 14744 OrAndSum
题意:给你$pairOr,pairSum$两个含有$n$个非负整数数组,问你是否能构造出一个数组$x[0] \cdots x[n]$满足$\forall \ {0\leqslant i \leqslant n-1}, x[i] \ or \ x[i+1] = pairOr[i] \ \wedge x[i] + x[i+1] = pairSum[i]$。
$a+b=a \ or \ b + a \ and \ b$
证:记$p_i,q_i$分别为$a,b$的第$k$位(二进制)。则
$$a+b=\sum_k(p_k+q_k)2^k$$
$$a \ or \ b=\sum_k(p_k\vee q_k)2^k$$
$$a \ and \ b=\sum_k(p_k \wedge q_k)2^k$$
$$a+b-a \ or \ b - a \ and \ b = \sum_k(p_k+q_k-p_k \wedge q_k - p_k \vee q_k)2^k=0$$
p | q | p+q | p or q | p and q |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 1 | 1 | 0 |
1 | 0 | 1 | 1 | 0 |
1 | 1 | 2 | 1 | 1 |
$$a + b = a \ or \ b + a \ and \ b$$
这样就能得到$pairOr,pairAnd$。
咱单独处理$x_i$二进制的每一位,因为知道了$pairOr,pairAnd$,所以只要知道$x_i$,就能知道$x_{i+1}$。每次都带入0或1看看行不行即可。
1 #include<cstdio> 2 #include<vector> 3 #include<string> 4 #include<iostream> 5 using namespace std; 6 class OrAndSum { 7 public: 8 string tak = "Possible", nie = "Impossible"; 9 bool check(int k, int x, vector < long long > a, vector < long long > b) { 10 for (int i = 0; i < a.size(); ++i) { 11 int _or = (a[i] >> k) & 1; int _and = (b[i] >> k) & 1; 12 if (_or && !_and) 13 x ^= 1; 14 if (_or && _and && !x) 15 return false; 16 if (!_or && _and) 17 return false; 18 if (!_or && !_and && x) 19 return false; 20 } return true; 21 } 22 string isPossible(vector < long long > pairOr, vector < long long > pairSum) { 23 vector < long long > &a = pairOr, &b = pairSum; 24 for (int i = 0; i < b.size(); ++i) b[i] -= a[i]; 25 for (int i = 0; i < b.size(); ++i) if (b[i] < 0) return nie; 26 for (int j = 0; j < 64; ++j) 27 if ((!check(j, 0, a, b)) && (!check(j, 1, a, b))) 28 return nie; 29 return tak; 30 } 31 };