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 };

 

posted @ 2018-01-19 12:01  p0ny  阅读(337)  评论(0编辑  收藏  举报