• 2021牛客暑期多校训练营8 D. OR(位运算/结论)


    链接:https://ac.nowcoder.com/acm/contest/11259/D
    来源:牛客网

    题目描述

    There are two sequences of length n−1n−1, b=(b2,b3,…,bn)b=(b2,b3,…,bn), c=(c2,c3,…,cn)c=(c2,c3,…,cn). Here, each bibi,cici is a non-negative integer.

    Now, the sequence a=(a1,a2,…,an)a=(a1,a2,…,an) considers beautiful if and only if forall ii (2≤i≤n)(2≤i≤n), bi=ai−1 or aibi=ai−1orai, ci=ai−1+aici=ai−1+ai and each aiai is a non-negative integer.

    Now, Toilet-Ares asks you to calculate the number of beautiful sequences.

    输入描述:

    The first line contains one integer nn (2≤n≤105)(2≤n≤105) - the length of sequence aa.
    
    The second line contains n−1n−1 integers b2,b3,…,bnb2,b3,…,bn (0≤bi<230)(0≤bi<230) - the elements of sequence bb.
    
    The third line contains n−1n−1 integers c2,c3,…,cnc2,c3,…,cn (0≤ci<231)(0≤ci<231) - the elements of sequence cc.
    

    输出描述:

    Print one number - the number of beautiful sequences.
    

    示例1

    输入

    复制

    4
    7 5 5
    7 9 5
    

    输出

    复制

    2
    

    做这个题关键就是要知道一个性质(x + y = x & y + x | y)。这样的话(c_i = a_i & a_{i-1} + a_i | a_{i-1}),则设(d_i=c_i-b_i=a_i& a_{i-1}),由此可以知道a数组相邻两个数进行与以及或得到的结果,排除掉了加法产生的进位的影响后,位与位之间就彼此不相关,可以套路地进行按位分析了。如果枚举(a_1)的每一位,根据前面得到的结论实际上就能够唯一确定出(a_2,a_3..a_n)的这一位的值(当然可能不存在),由此也就知道了整个a数组。所以现在要做的就是从高往低或者从低往高枚举(a_1)的每一位,这一位可以为0也可以为1,如果这一位为0成立(即设这一位为0,可以依次得到(a_2,a_3..a_n)的这一位而不引起矛盾)为1也成立,由乘法原理将答案乘2,如果为0为1都不成立则答案为0且终止循环,否则对答案没有贡献,答案不变。

    #include <bits/stdc++.h>
    using namespace std;
    int n, a[100005], b[100005], c[100005], d[100005];
    int main() {
    	cin.tie(0);
    	ios::sync_with_stdio(false);
    	cin >> n;
    	for(int i = 2; i <= n; i++) cin >> b[i];
    	for(int i = 2; i <= n; i++) cin >> c[i];	
    	for(int i = 2; i <= n; i++) {
    		d[i] = c[i] - b[i];
    	}
    	long long ans = 1;
    	for(int i = 0; i < 30; i++) {//枚举a[1]的每一位 要么为0要么为1
    		bool zero = 1, one = 1;
    		vector<int> v(n + 1);//用来存储a1到an第i位的结果
    		v[1] = 0;//a1的第i位为0的话
    		for(int j = 2; j <= n; j++) {//判断是否合法
    			int nb = (b[j] >> i) & 1, nd = (d[j] >> i) & 1;//获取b数组和d数组第j个元素的第i位
    			if(nd) {
    				if(nb) {//aj-1和aj的第i位相与为1 相或也为1
    					if(v[j - 1]) {//如果aj-1的第i位是1
    						v[j] = 1;//aj的第i位也是1
    					} else {//否则根据与或的性质就有矛盾了
    						zero = 0;
    						break;
    					}
    				} else {//相与为1相或为0,必然不可能
    					zero = 0;
    					break;
    				}
    			} else {
    				if(nb) {
    					if(v[j - 1]) {
    						v[j] = 0;
    					} else {
    						v[j] = 1;
    					}
    				} else {
    					if(v[j - 1]) {
    						zero = 0;
    						break;
    					} else {
    						v[j] = 0;
    					}
    				}
    			}
    		}
    		v[1] = 1;//a1的第i位为1的话
    		for(int j = 2; j <= n; j++) {
    			int nb = (b[j] >> i) & 1, nd = (d[j] >> i) & 1;
    			if(nd) {
    				if(nb) {
    					if(v[j - 1]) {
    						v[j] = 1;
    					} else {
    						one = 0;
    						break;
    					}
    				} else {
    					one = 0;
    					break;
    				}
    			} else {
    				if(nb) {
    					if(v[j - 1]) {
    						v[j] = 0;
    					} else {
    						v[j] = 1;
    					}
    				} else {
    					if(v[j - 1]) {
    						one = 0;
    						break;
    					} else {
    						v[j] = 0;
    					}
    				}
    			}
    		}
    		if(zero && one) ans *= 2;
    		else if(zero ^ one) ans *= 1;
    		else {
    			ans = 0;
    			break;
    		}
    	}
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    Winform打包Exe Inno Setup
    electron build慢
    electron解压app.asar文件
    input readonly 禁止获得焦点 和选择
    JS export
    数据库插件 red-gate SQLToolbelt
    DataGridView修改值后,最后一个修改项页面不会刷新
    DbDataReaderExtensions DbDataRender转换为实体
    反射获得实体
    LINQ Expression AndAlso,OrElse和And,Or的区别
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15120615.html
Copyright © 2020-2023  润新知