2021牛客多校训练营8
D
题意描述
有两个长度为\(n - 1\)的整数序列\(b=\{b_{2},b_{3}...b_{n}\}\),\(c=\{c_{2},c_{3}...c_{n}\}\),其中\(b_{i}=a_{i-1} \ | \ a_{i}\),\(c_{i}=a_{i-1}+a_{i}\),求满足该条件的\(a\)序列的个数
思路
由于\(a|b=a+b-a\&b\),所以\(c[i]-b[i]=a_{i}\&a_{i-1}=d_{i}\)。此时我们就得到了\(a_{i}\)的两个限制,由于每一位都是独立的且确定了\(a_{1}\)我们就能得到整个\(a\)序列,所以我们可以枚举\(a_{1}\)的每一位来进行判断。
定义\(lstbit0\)为上一位是0的状态,有两种取值\(0/1\)(下面定义的都是这两种取值),为\(0\)表示不能为\(0\),为\(1\)表示可以为\(0\),\(lstbit1\)表示上一位是1的状态,\(nowbit1\)表示当前位为\(1\)的状态,\(nowbit0\)表示当前位为\(0\)的状态,则当前位的贡献则为\(bit0+bit1\)。我们列出一个表格如下:
| b | 0 | 0 | 1 | 1 |
|---|---|---|---|---|
| d | 0 | 1 | 0 | 1 |
| nowbit0 | lstbit0 | 0 | lstbit1 | 0 |
| nowbit1 | 0 | 0 | lstbit0 | lstbit1 |
| 然后根据表格枚举每一位判断即可 |
代码
#include
using ll = long long;
const int N = 1e5 + 5;
int a[N], b[N], c[N], n, d[N];
void solve()
{
std::cin >> n;
for(int i = 2; i <= n; ++i) std::cin >> b[i];
for(int i = 2; i <= n; ++i) std::cin >> c[i];
for(int i = 2; i <= n; ++i) d[i] = c[i] - b[i];
ll ans = 1;
for(int i = 0; i < 32; ++i)
{
int bit0 = 1, bit1 = 1;
for(int j = 2; j <= n; ++j)
{
int nowbit0 = 0, nowbit1 = 0;
int x = b[j] >> i & 1, y = d[j] >> i & 1;
if(!x && !y) nowbit0 = bit0;
else if(x && !y) nowbit0 = bit1, nowbit1 = bit0;
else if(x && y) nowbit1 = bit1;
bit0 = nowbit0, bit1 = nowbit1;
}
ans *= (bit0 + bit1);
}
std::cout << ans << '\n';
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int t = 1;
while(t--) solve();
}