トップページに戻る
次の競技プログラミングの問題へ
前の競技プログラミングの問題へ
ABC-125-C GCD on Blackboard
■■■問題■■■
N個の整数 A1 , A2 , ・・・ , AN が黒板に書かれています。
あなたはこの中から整数を1つ選んで、1以上10億以下の好きな整数に書き換えます。
元の整数と同じ整数に書き換えても構いません。
書き換えた後のN個の整数の最大公約数の最大値を求めてください。
■■■入力■■■
N
A1 A2 ・・・ AN
●入力は全て整数である
●2 <= N <= 10万
●1 <= Ai <= 10億
■■■出力■■■
書き換えた後のN個の整数の最大公約数の最大値を出力せよ。
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");
WillReturn.Add("7 6 8");
//2
//7を4に書き換えると3つの整数の最大公約数は2となり、これが最大です。
}
else if (InputPattern == "Input2") {
WillReturn.Add("3");
WillReturn.Add("12 15 18");
//6
}
else if (InputPattern == "Input3") {
WillReturn.Add("2");
WillReturn.Add("1000000000 1000000000");
//1000000000
//元の整数と同じ整数に書き換えることも可能です。
}
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(X => int.Parse(X)).ToArray();
int UB = AArr.GetUpperBound(0);
//左からの累積GCDを求める
int[] GCDArrLeft = new int[UB + 1];
GCDArrLeft[0] = AArr[0];
for (int I = 1; I <= UB; I++) {
GCDArrLeft[I] = DeriveGCD(GCDArrLeft[I - 1], AArr[I]);
}
//右からの累積GCDを求める
int[] GCDArrRight = new int[UB + 1];
GCDArrRight[UB] = AArr[UB];
for (int I = UB - 1; 0 <= I; I--) {
GCDArrRight[I] = DeriveGCD(GCDArrRight[I + 1], AArr[I]);
}
int Answer = 0;
for (int I = 0; I <= UB; I++) {
int CurrGCD = 0;
if (I == 0) {
CurrGCD = GCDArrRight[1];
}
else if (I == UB) {
CurrGCD = GCDArrLeft[UB - 1];
}
else {
CurrGCD = DeriveGCD(GCDArrLeft[I - 1], GCDArrRight[I + 1]);
}
Answer = Math.Max(Answer, CurrGCD);
}
Console.WriteLine(Answer);
}
//ユークリッドの互除法で2数の最大公約数を求める
static private int DeriveGCD(int pVal1, int pVal2)
{
pVal1 = Math.Abs(pVal1);
pVal2 = Math.Abs(pVal2);
int WarareruKazu = Math.Max(pVal1, pVal2);
int WaruKazu = Math.Min(pVal1, pVal2);
while (true) {
int Amari = WarareruKazu % WaruKazu;
if (Amari == 0) return WaruKazu;
WarareruKazu = WaruKazu;
WaruKazu = Amari;
}
}
}
解説
最初に、
左からの累積GCDと
右からの累積GCDを事前に求めます。
次に、
各値ごとに、その値だけを除外した場合のGCDを、順番に求めてます。