AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC161-F Division or Subtraction
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("6");
//3
}
else if (InputPattern == "Input2") {
WillReturn.Add("3141");
//13
}
else if (InputPattern == "Input3") {
WillReturn.Add("314159265358");
//9
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long mN;
static void Main()
{
List<string> InputList = GetInputList();
mN = long.Parse(InputList[0]);
var KouhoSet = new HashSet<long>();
long[] YakusuuArr1 = DeriveYakusuuArr(mN);
long[] YakusuuArr2 = DeriveYakusuuArr(mN - 1);
Array.ForEach(YakusuuArr1, pX => KouhoSet.Add(pX));
Array.ForEach(YakusuuArr2, pX => KouhoSet.Add(pX));
Console.WriteLine(KouhoSet.Count(pX => IsOK(pX)));
}
// Kを引数として、解として適切かを判定
static bool IsOK(long pK)
{
if (pK < 2 || mN < pK) return false;
long CurrN = mN;
while (true) {
if (CurrN == 1) return true;
if (CurrN < pK) return false;
if (CurrN % pK == 0) {
CurrN /= pK;
}
else {
CurrN %= pK;
}
}
}
// 約数を列挙する
static long[] DeriveYakusuuArr(long pTarget)
{
var YakusuuSet = new HashSet<long>();
for (long I = 1; I * I <= pTarget; I++) {
if (pTarget % I == 0) {
YakusuuSet.Add(I);
YakusuuSet.Add(pTarget / I);
}
}
long[] YakusuuArr = YakusuuSet.ToArray();
Array.Sort(YakusuuArr);
return YakusuuArr;
}
}
解説
KがNの約数かで場合に分けて考えます。
KがNの約数の場合は、ナイーブにシュミレーションします。
KがNの約数でない場合は、
例えば123は5の倍数でないですが
5の倍数でない数から5を引いても、5の倍数でないです。
なので、最終的な値は 123 % 5 で 3 になると分かります。
よって
N ≡ 1 mod K
が成り立つかを判定すれば良いですが、
N ≡ 1 mod K が成り立つ必要条件として
Kが(N-1)の約数という条件があります。
以上の2つの場合分けにより、
Nの約数と、(N-1)の約数の和集合を求めて
ナイーブに解として適切かを判定すれば良いです。