牛客多校2021(八)D. OR(位运算)
-
题目:OR
-
题意:给出一个长度为(n - 1)的序列\(b_i\)和\(c_i\),问存在多少个a序列,满足所有(\(1 \leq i\leq n\))
\[\begin{align*} a_{i-1}|a_i = b_i, \ a_{i-1}+a_i = c_i \end{align*} \] -
解析:有如下性质并可以进行推导:
\[\begin{align*} & a_{i-1}+a_i = a_{i-1}|a_i + a_{i-1}\&a_i \\ & \because b_i = a_{i-1} | a_i\\ & \therefore 令d_i = c_i - b_i = a_{i-1}\&a_i \\ & 即:a序列(1 \leq i \leq n)满足:a_{i-1}|a_i = b_i, \ a_{i-1}\&a_i = d_i 即可\\ \end{align*} \]并且我们可以发现,只要\(a_1\)确定之后,之后的\(a_i\)一定是确定的(\(a_i\)由\(b_i\)和\(c_i\)决定),那么我们可以通过枚举int范围内的\(a_1\)也就是枚举其每一位是否可以为0或者为1,每一位至多有两种方案,最后用乘法原理将所有方案数相乘即可,下面是枚举到第\(k\)位时的情况:
\(b_i\) \(d_i\) \(a_i\) \(a_{i-1}\) 0 0 0 0 1 1 1 1 1 0 1 0 0 1 0 1 null null 举个例子:当\(b_i\) = 0, \(d_i\) = 0时候,若要满足上诉条件必须使得\(a_i\) = 0, \(a_{i-1}\) = 0才能满足,否则若\(a_{i-1}\) = 1, 那么这种方案则不存在。
-
代码:
#include<iostream> #include<cstdio> using namespace std; typedef long long ll; const int N = 1e5 + 5; int n; int b[N], c[N], d[N]; ll res = 1; ll solve(int pos, int k, int pre) //第pos个数、第pos个数的第k位、a[pos - 1]的第k位 { if(pos > n) return 1; int x = b[pos] >> k & 1, y = d[pos] >> k & 1; //取出第pos个数的第k位 int now = -1; //第k + 1位取的值(1或0) for(int i = 0; i <= 1; i++) //判断ai = 0/1是否满足条件(只可能是其中之一满足,因为a(i-1)已经确定) { if(x == (pre | i) && y == (pre & i) ) now = i; } if(now == -1) return 0; //找不到满足条件的ai else return solve(pos + 1, k, now); } int main() { cin >> n; for(int i = 2; i <= n; i++) cin >> b[i]; for(int i = 2; i <= n; i++) { cin >> c[i]; d[i] = c[i] - b[i]; } for(int i = 0; i <= 31; i++) { res *= solve(2, i, 0) + solve(2, i, 1); } cout << res << endl; return 0; }

浙公网安备 33010602011771号