yukicoder
前のyukicoderの問題へ
yukicoder 3624 Product
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("4");
WillReturn.Add("1 4");
WillReturn.Add("8 15");
WillReturn.Add("45 123");
WillReturn.Add("0 1000000000");
//12
//-1
//4032
//288230375614840832
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long[] GetSplitArr(string pStr)
{
return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = (pStr) => wkArr = GetSplitArr(pStr);
foreach (string EachStr in InputList.Skip(1)) {
SplitAct(EachStr);
long L = wkArr[0];
long R = wkArr[1];
long Answer = Solve(L, R);
Console.WriteLine(Answer);
}
}
static long Solve(long pL, long pR)
{
if (pL == 0 && pR == 0) return 0;
string BinStrL = Convert.ToString(pL, 2);
string BinStrR = Convert.ToString(pR, 2);
int Length = Math.Max(BinStrL.Length, BinStrR.Length);
BinStrL = BinStrL.PadLeft(Length, '0');
BinStrR = BinStrL.PadLeft(Length, '0');
if (BinStrL[0] == '1' && BinStrR[0] == '1') return -1;
string NewBinStrL = "0";
string NewBinStrR = "1";
for (long I = 1; I <= Length - 1; I++) {
NewBinStrL += 1;
NewBinStrR += 0;
}
long LongValL = Convert.ToInt64(NewBinStrL, 2);
long LongValR = Convert.ToInt64(NewBinStrR, 2);
return LongValL * LongValR;
}
}
解説
まず、LとRが0の場合、解は0になります。
LとRが、両方0より大きい場合を考えます。
2進数で考えると、場合分けができます。
最大長に合わせて、0を左パディングします。
場合1
下限が 1XXX
上限が 1XXX
これは、必ずBitAndが1以上になるので、解は-1です。
場合2
下限が 0XXX
上限が 1XXX
0XXXが範囲下限の場合、最大上界である
0111は必ず使用できます。
下限が 0XXX
上限が 1XXX
1XXXが範囲上限の場合、最小下界である
1000は必ず使用できます。
そして、BitAndを0、かつ、積は最大化したいので
0111と1000のペアが最適解となります。