2021牛客暑期多校训练营8 D. OR

题意:给你长度为n-1的数列b和c,问有多少种合法的a使得b[i]=a[i-1]|a[i],c[i]=a[i-1]+a[i]

首先我们有x&y + x|y = x+y
(记得NOIP初赛考过这个,当时还不知道

那么相当于我们有了a数列每两项之间的and以及or关系,

这个条件比相加好用很多,套路地拆位考虑就行

#include <bits/stdc++.h>
#define int long long
using namespace std;

int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN = 100005;

int n;
int b[MAXN],d[MAXN];
int f[MAXN][2];

signed main(){
    n=rd();
    for(int i=2;i<=n;i++)
        b[i]=rd();
    for(int i=2;i<=n;i++)
        d[i]=rd()-b[i];
    int ans=1;
    for(int k=30;k>=0;k--){
        memset(f,0,sizeof(f));
        f[1][0]=f[1][1]=1;
        int tmp=(1<<k);
        for(int i=2;i<=n;i++){
            bool u=(tmp&b[i]),v=(tmp&d[i]);
            if(u==0&&v==0){
                f[i][0]=f[i-1][0];
                f[i][1]=0;
            }else if(u==1&&v==0){
                f[i][0]=f[i-1][1];
                f[i][1]=f[i-1][0];
            }else if(u==0&&v==1){
                f[i][0]=0;
                f[i][1]=0;
            }else{
                f[i][1]=f[i-1][1];
                f[i][0]=0;
            }
        }
        ans*=(f[n][0]+f[n][1]);
    }
    cout<<ans;
    return 0;
}
posted @ 2021-08-09 19:06  GhostCai  阅读(44)  评论(0编辑  收藏  举报