原題鏈接:76D Plus and xor (dp, greedy, math, *1700)
題意簡(jiǎn)述
給定兩個(gè)數(shù) 螟蒸,你需要構(gòu)造出兩個(gè)數(shù)
,使得
且
的同時(shí)靠汁,
盡量小舌胶。
解法分析
一道很 CF 的構(gòu)造題秕狰。
首先,根據(jù)異或不進(jìn)位加法的性質(zhì),兩個(gè)數(shù)的異或和不超過(guò)它們的和扒袖,因此當(dāng) 時(shí)無(wú)解胰蝠。
同樣根據(jù)不進(jìn)位加法的性質(zhì)歼培,我們知道 與
的奇偶性必定相同震蒋,即
必定為偶數(shù),否則無(wú)解躲庄,剩余情況均有解查剖。
我們考慮如何構(gòu)造符合條件的 同時(shí)
盡量小:
如果 和
有一位二進(jìn)制位同為
噪窘,則加法后為
笋庄,異或后為
,將兩者的差右移
倔监,得到
直砂。我們可以通過(guò)這種辦法得到
中均為
的位。因此
的結(jié)果就是兩數(shù)中均為
的位浩习。
同時(shí)静暂,根據(jù)加法和異或的性質(zhì)蔽莱,兩數(shù)同一位上的 和
可以互換缴淋。為了讓
盡量小,我們令
即可见妒,可以用
求出
疟赊。
注意數(shù)據(jù)范圍郊供,需要使用 unsigned long long。
代碼
//By: Luogu@rui_er(122461)
#include <bits/stdc++.h>
#define loop while(true)
#define rep(x,y,z) for(ll x=y;x<=z;x++)
#define per(x,y,z) for(ll x=y;x>=z;x--)
#define fil(x,y) memset(x, y, sizeof(x))
using namespace std;
typedef unsigned long long ll;
ll a, b, x, y;
int main() {
scanf("%llu%llu", &a, &b);
if(a < b || (a - b) & 1) return puts("-1"), 0;
x = (a - b) / 2; y = a - x;
printf("%llu %llu\n", x, y);
return 0;
}