OR
题意:
给你一个数组b和c(数值位于下标2到n)
问是否存在一个a序列,bi=ai−1oraibi=a_{i-1} or a_{i}bi=ai−1orai , ci=ai−1+aic_{i}=a_{i-1}+a_{i}ci=ai−1+ai
题解:
我是这样想的,对于每一个bi和ci(i从2开始),都可以确定ai的取值情况,然后我们再计算bi+1和ci+1时,可以根据上一轮ai得到的情况来确定本轮ai+1的情况。
如何通过bi和ci确定ai的取值呢?
我们利用二进制来判断,对于bi和ci的每一位分析,从第0位到第31位依次分析,
- 考虑第j位时,f表示当前是否有进位
- 如果b=0,c=0,f=0,那么ai,ai-1的第j位为0
- 如果b=1,c=1,f=1,那么ai,ai-1为1
- 如果b=1,c=1,f=1,那么ai和ai-1一个为0,一个为1
- 如果b=1,c=0,f=1,那么ai和ai-1一个为0
- 如果b=1,c=0,f=0,那么ai,ai-1为1,且会产生进位f=1
- 如果b=0,c=1,f=1,那么ai,ai-1为0,进位在此处用掉,进位消失,f=0
- 不满足上列情况,a无法取到值
F[i]表示第i个位置的情况
F[i]=2表示第i个位置有两个值可以取,如果ai取1,则ai-1取0,反之(初始化为-1)
F[i]=1/0:分别表示当前位置取1或0
F[i]=-1:说明当前位置无法取到值
F[i]会不断更新,F[i]的作用相当于将Ai的取值情况与Ai-1相连(Ai-1的情况就是通过F[i]来表示),完事后并更新F[i],给后面Ai+1接着使用
w表示当前第j位的取值情况
- 如果w=-1,则F[i]=-1
- 如果w=0/1&&F[j]==2,则F[j]=w
- 如果w=2&&F[j]!=2,则F[j]=F[j] ^ 1(ai-1这一个位置取w(0或1),而ai与ai-1是两种取值,ai的取值是w ^ 1)
- 如果w=0&&F[j]=1,则F[j]=-1;
- 如果w=1&&F[j]=0,则F[j]=-1;
然后更新答案
详细看代码
代码:
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
void rd_test(){#ifdef ONLINE_JUDGE#elsestartTime = clock(); //计时开始freopen("in.txt","r",stdin);#endif
}
void Time_test(){#ifdef ONLINE_JUDGE#elseendTime = clock(); //计时结束printf("\n运行时间为:%lfs\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);#endif
}
const int maxn=2e5+9;
ll b[maxn],c[maxn],F[maxn];
int main()
{//rd_test();int n;cin>>n;ll sum=1e11;for(int i=2;i<=n;i++){cin>>b[i];}for(int i=2;i<=n;i++){cin>>c[i];}for(int i=0;i<=33;i++)F[i]=2; for(int i=2;i<=n;i++){ll tot=1;ll w=0;int f=0;for(int j=0;j<=31;j++){int x=((b[i]>>j)&1);int y=((c[i]>>j)&1);if(x==0&&y==0&&f==0)w=0;else if(x==1&&y==1){if(f==1){w=1;}else w=2;}else if(x==1&&y==0){if(f==1){w=2;f=1;}else{w=1;f=1;} }else if(x==0&&y==1&&f==1){f=0;w=0;}else {w=-1;}if(w==-1)F[j]=-1;else if(F[j]==2&&w!=2) F[j]=w;else if(w==2&&F[j]!=2)F[j]=F[j]^1;else if(F[j]==1&&w==0)F[j]=-1;else if(F[j]==0&&w==1) F[j]=-1;if(F[j]==1)tot=1ll*tot*1;else if(F[j]==0)tot=1ll*tot*1;else if(F[j]==2)tot=1ll*tot*2;else if(F[j]==-1)tot=1ll*tot*0;}if(f==1)tot=0;sum=min(sum,tot);}cout<<sum;//Time_test();
}