AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC347-D Popcount and XOR
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("3 4 7");
//28 27
}
else if (InputPattern == "Input2") {
WillReturn.Add("34 56 998244353");
//-1
}
else if (InputPattern == "Input3") {
WillReturn.Add("39 47 530423800524412070");
//540431255696862041 10008854347644927
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = InputList[0].Split(' ').Select(pX => long.Parse(pX)).ToArray();
long RestPopCntA = wkArr[0];
long RestPopCntB = wkArr[1];
long XOR = wkArr[2];
long AVal = 0;
long BVal = 0;
var BitValDict = new Dictionary<long, long>();
long CurrVal = 1;
for (long I = 1; I <= 60; I++) {
BitValDict[I] = CurrVal;
CurrVal *= 2;
}
for (long I = 1; I <= 60; I++) {
long BitAnd = BitValDict[I] & XOR;
if (BitAnd > 0) {
if (RestPopCntA == 0 && RestPopCntB == 0) {
Console.WriteLine(-1);
return;
}
if (RestPopCntA < RestPopCntB) {
BVal += BitValDict[I];
RestPopCntB--;
}
else {
AVal += BitValDict[I];
RestPopCntA--;
}
}
}
for (long I = 1; I <= 60; I++) {
long BitAnd = BitValDict[I] & XOR;
if (BitAnd == 0) {
if (RestPopCntA > 0 && RestPopCntB > 0) {
BVal += BitValDict[I]; RestPopCntB--;
AVal += BitValDict[I]; RestPopCntA--;
}
}
}
// 十分性のチェック1
if (RestPopCntA > 0 || RestPopCntB > 0) {
Console.WriteLine(-1);
return;
}
// 十分性のチェック2
if ((AVal ^ BVal) != XOR) {
Console.WriteLine(-1);
return;
}
Console.WriteLine("{0} {1}", AVal, BVal);
}
}
解説
残りのPopCntを管理しつつ、
以下のロジックで解いてます。
手順1
最終XORが1の箇所を走査し、
残りのPopCntが多いほう優先で、1を立てる。
手順2
最終XORが0の箇所は、
両方に1を立てるか、両方に立てないようにする。
手順3
十分性をチェックする。