nとdを正の整数として, 分数 n/d を考えよう. n<d かつ HCF(n,d) = 1のとき、真既約分数と呼ぶ. d <= 8 について真既約分数を大きさ順に並べると, 以下を得る: 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8 1/3と1/2の間には3つの分数が存在することが分かる. では, d <= 12000 について真既約分数をソートした集合では, 1/3 と 1/2 の間に何個の分数があるか?
using System; class Program { //const int MaxD = 8; const int MaxD = 12000; static void Main() { int AnswerCnt = 0; for (int D = 1; D <= MaxD; D++) { int MinVal = DeriveMinSeisuuKai(D); int MaxVal = DeriveMaxSeisuuKai(D); if (MaxVal == 0) continue; for (int N = MinVal; N <= MaxVal; N++) { //分子と分母が互いに素なら既約分数 if (DeriveGCD(D, N) == 1) { AnswerCnt++; if (D > 8) continue; Console.WriteLine("解{0}を発見。1/3 < {1}/{2} < 1/2", AnswerCnt, N, D); } } } Console.WriteLine("答えは{0}", AnswerCnt); } //分母を引数として、不等式 分子/分母 > 1/3 の最小の整数解を求める static int DeriveMinSeisuuKai(int pBunbo) { return pBunbo / 3 + 1; } //分母を引数として、不等式 分子/分母 < 1/2 の最大の整数解を求める static int DeriveMaxSeisuuKai(int pBunbo) { bool NeedKurisage = (pBunbo % 2 == 0); int WillReturn = pBunbo / 2; return (NeedKurisage ? WillReturn - 1 : WillReturn); } //ユークリッドの互除法で2数の最大公約数を求める static int DeriveGCD(int pVal1, int 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; } } }
解1を発見。1/3 < 2/5 < 1/2 解2を発見。1/3 < 3/7 < 1/2 解3を発見。1/3 < 3/8 < 1/2 答えは7295372
分母ごとに 不等式 分子/分母 < 2/1 の最大の整数解と、 不等式 分子/分母 > 3/1 の最小の整数解を求めてから、 真既約分数の数を数えてます。