Codeforces 734F. Anton and School (思维 + 二进制)

Description
Anton goes to school, his favorite lessons are arraystudying. He usually solves all the tasks pretty fast, but this time the teacher gave him a complicated one: given two arrays b and c of length n, find array a, such that:

where a and b means bitwise AND, while a or b means bitwise OR.

Usually Anton is good in arraystudying, but this problem is too hard, so Anton asks you to help.

Input
The first line of the input contains a single integers n (1 ≤ n ≤ 200 000) — the size of arrays b and c.

The second line contains n integers b i ( 0   ≤   b i   ≤   1 0 9 ) b_i (0 ≤ b_i ≤ 10^9) bi(0bi109) — elements of the array b.

Third line contains n integers c i ( 0   ≤   c i   ≤   1 0 9 ) c_i (0 ≤ c_i ≤ 10^9) ci(0ci109) — elements of the array c.

Output
If there is no solution, print  - 1.

Otherwise, the only line of the output should contain n non-negative integers a i a_i ai — elements of the array a. If there are multiple possible solutions, you may print any of them.

Examples
Input
4
6 8 4 4
16 22 10 10
Output
3 5 1 1

Input
5
8 25 14 7 16
19 6 9 4 25
Output
-1

Solution
这题的核心在于一个公式:
( a   a n d   b ) + ( a   o r   b ) = = a + b (a~and~b) + (a~or~b) == a + b (a and b)+(a or b)==a+b
稍微推一下不难发现:
对于所有的 i i i 都有 b i + c i = = n ∗ a i + s u m a b_i + c_i ==n*a_i + sum_a bi+ci==nai+suma
我们可以求出每个 a i a_i ai 的值,并且求出的值为唯一可能解
但是这个唯一可能解也可能不合法,因为我们只保证了 b i + c i b_i + c_i bi+ci符合条件
不能暴力check,考虑记录下二进制每一位有多少个1,从而实现 O ( 32 ) O(32) O(32) check每个位置

Code

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#include <cstring>
#define pb push_back
#define pii pair<int,int>
#define mpp make_pair
#define fi first
#define se second
#define re register
#define clr(a,b) memset(a,b,sizeof(a))

// //debug
// #define FIN freopen("in.txt","r",stdin);
#define debug1(x) cout << "[" << #x << " = " << (x) << "]\n"
#define debug2(x,y) cout << "[" << #x << " = " << (x) << "  " << #y << " = " << (y) << "]\n"
#define debug3(x,y,z) cout << "[" << #x << " = " << (x) << "  " << #y << " = " << (y) << "  " << #z << " = " << (z) << "]\n"


using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll LINF = 2e18 + 7;
const int mod = 1e9 + 7;
const double eps = 1e-6;

const int maxn = 8e6 + 7;
const int maxm = 2e5 + 7;

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a % b);
}
ll b[maxn], c[maxn];
int a[maxn];
ll sum = 0;
int num[40];
bool check(int n){
	int maxbit = 0;
	for(int i = 1;i <= n;++i){
		ll tmp = a[i];
		int pos = 0;
		while(tmp){
			if(tmp % 2) num[pos]++;
			pos++; tmp /= 2; 
			maxbit = max(maxbit,pos);
		}
	}
	for(int i = 1;i <= n;++i){
		int tmp = a[i], pos = 0;
		ll tot = 0;
		for(int j = 0;j < maxbit;++j){
			int m = tmp % 2;
			if(m) tot += 1ll * (1<<j) * num[j];
			tmp /= 2;
		}
		if(tot != b[i]) return false;
	}
	for(int i = 1;i <= n;++i){
		int tmp = a[i], pos = 0;
		ll tot = 0;
		for(int j = 0;j < maxbit;++j){
			int m = tmp % 2;
			if(m) tot += 1ll * (1<<j) * n;
			else tot += 1ll * (1<<j) * num[j];
			tmp /= 2;
		}
		if(tot != c[i]) return false;
	}
	return true;
}
int main() {
	int n;scanf("%d",&n);
	for(int i = 1;i <= n;++i){
		scanf("%lld",&b[i]);
		sum += b[i];
	}
	for(int i = 1;i <= n;++i){
		scanf("%lld",&c[i]);
		sum += c[i];
	}
	if(sum % (2*n) != 0) {
		printf("-1\n"); return 0;
	}
	ll suma = sum / (1ll*2*n);	
	for(int i = 1;i <= n;++i){
		ll tot = b[i] + c[i];
		tot -= suma;
		if(tot < 0 || tot % n != 0) {printf("-1\n"); return 0;}
		a[i] = tot / n;
	}
	ll tmp = 0;
	for(int i = 1;i <= n;++i) tmp += a[i];
	if(tmp != suma) printf("-1\n");
	else{
		if(!check(n)) {printf("-1\n"); return 0;}
		for(int i = 1;i <= n;++i) printf("%d ", a[i]);
		printf("\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值