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
十分性をチェックする。