AtCoderのARC
次のARCの問題へ
前のARCの問題へ
ARC135-C XOR to All
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("5");
WillReturn.Add("1 2 3 4 5");
//19
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("10 10 10 10 10");
//50
}
else if (InputPattern == "Input3") {
WillReturn.Add("5");
WillReturn.Add("3 1 4 1 5");
//18
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
int[] AArr = InputList[1].Split(' ').Select(pX => int.Parse(pX)).ToArray();
// Onの件数[2のべき乗]なDict
var OnCntDict = new Dictionary<long, long>();
// Offの件数[2のべき乗]なDict
var OffCntDict = new Dictionary<long, long>();
long MaxA = AArr.Max();
for (long Loop2Beki = 1; Loop2Beki <= MaxA; Loop2Beki *= 2) {
OnCntDict[Loop2Beki] = 0;
OffCntDict[Loop2Beki] = 0;
foreach (long EachA in AArr) {
if ((EachA & Loop2Beki) > 0) {
OnCntDict[Loop2Beki]++;
}
else {
OffCntDict[Loop2Beki]++;
}
}
}
// 解候補を列挙
var AnswerKouhoList = new List<long>();
long DefaultVal = 0;
foreach (var EachPair in OnCntDict) {
DefaultVal += EachPair.Key * EachPair.Value;
}
AnswerKouhoList.Add(DefaultVal);
foreach (long EachA in AArr) {
long AnswerKouho = 0;
for (long Loop2Beki = 1; Loop2Beki <= MaxA; Loop2Beki *= 2) {
if ((EachA & Loop2Beki) > 0) {
AnswerKouho += Loop2Beki * OffCntDict[Loop2Beki];
}
else {
AnswerKouho += Loop2Beki * OnCntDict[Loop2Beki];
}
}
AnswerKouhoList.Add(AnswerKouho);
}
Console.WriteLine(AnswerKouhoList.Max());
}
}
解説
A B C D
があるとしてAとXORを取ると
0 (B XOR A) (C XOR A) (D XOR A)
になります。
次に、2項目の(B XOR A)とXORを取ると
(A XOR B) 0 (C XOR B) (D XOR B)
になるので、
2回以上XORを取るのは無駄と分かります。
よって、前処理で
ビットごとに0と件数と1の件数を求めておけば、TLEせずに解けます。