D题:OR
题目大意
solution
对于输入,因为
a
+
b
=
a
∣
b
+
a
&
b
a+b=a|b+a\&b
a+b=a∣b+a&b,当知道
a
i
+
a
i
−
1
a_i+a_{i-1}
ai+ai−1和
a
i
∣
a
i
−
1
a_i|a_{i-1}
ai∣ai−1的值时,就可以求出
a
i
&
a
i
−
1
a_i\&a_{i-1}
ai&ai−1的值。
枚举
a
i
,
a
i
−
1
a_i,a_{i-1}
ai,ai−1转成二进制后第k位 的0,1分布情况。
共4种00,01,10,11。只有当
a
i
,
a
i
−
1
a_i,a_{i-1}
ai,ai−1中一个为1,一个为0时,才会存在2种可能,否则全为1或全为0只有1种可能。对于0,1分布情况可以根据开始求出的
a
i
∣
a
i
−
1
a_i|a_{i-1}
ai∣ai−1和
a
i
&
a
i
−
1
a_i\&a_{i-1}
ai&ai−1的值的第k位判断,在第k位的可能数要满足所有
a
i
,
a
i
−
1
a_i,a_{i-1}
ai,ai−1,于是枚举所有
a
i
i
:
2
→
n
a_i\small i:2\to n
aii:2→n。
数据最大到
2
30
2^{30}
230所以枚举
k
:
0
→
30
k:0\to 30
k:0→30,最终的答案是每位上可能数的总乘积,
A
n
s
=
Π
k
=
0
30
n
u
m
k
Ans=\Pi_{k=0}^{30}num_k
Ans=Πk=030numk
code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+7;
ll b[N],c[N],d[N],n;
ll ans=1,dp[N][2];
int main()
{
scanf("%d",&n);
for (int i=2;i<=n;i++)
scanf("%d",&b[i]);
for (int i=2;i<=n;i++)
scanf("%d",&c[i]);
for (int i=2;i<=n;i++)
d[i]=c[i]-b[i];//求a[i]&a[i-1]
for(int k=0;k<=30;k++)
{
for(int j=0;j<=n;j++)
dp[j][0]=dp[j][1]=0;
dp[1][0]=dp[1][1]=1;
for(int i=2;i<=n;i++){
for(int p=0;p<=1;p++){
for(int q=0;q<=1;q++){
if((p|q)==((b[i]>>k)&1)&&(p&q)==((d[i]>>k)&1))
dp[i][p]=dp[i-1][q];//储存可能方案
}
}
}
ans*=(dp[n][0]+dp[n][1]);//累计答案
}
printf("%d\n",ans);
return 0;
}