Project Euler

Project Euler 問題26(逆数のサイクル)を解いてみる

Euler_026

Project Euler で紹介されている問題26を解いてみました。単位分数の周期を求める問題を紹介します。

Project Euler 問題26(逆数のサイクル)

単位分数とは、分子が1の分数である。分母が2から10の単位分数の10進数表現は以下となる。

 1/2 = 0.5
 1/3 = 0.(3)
 1/4 = 0.25
 1/5 = 0.2
 1/6 = 0.1(6)
 1/7 = 0.(142857)
 1/8 = 0.125
 1/9 = 0.(1)
 1/10 = 0.1

ここでは、0.1(6) は、0.1666 …. を意味し、1桁の繰り返しの周期を持つ。1/7 は、6桁の周期が繰り返されることが分かる。

1/d (d < 1000) の小数の部分で最も長い周期を含む d の値を求めよ。

解答例

1/7 について、計算の構造を示します。

  • 1 を 10 倍した 10 を 7 で割ると、1 と余り 3 を得る。
  • 3 を 10 倍した 30 を 7 で割ると、4 と余り 2 を得る。
  • 2 を 10 倍した 20 を 7 で割ると、2 と余り 6 を得る。
  • 6 を 10 倍した 60 を 7 で割ると、8 と余り 4 を得る。
  • 4 を 10 倍した 40 を 7 で割ると、5 と余り 5 を得る。
  • 5 を 10 倍した 50 を 7 で割ると、7 と余り 1 を得る。
  • 1 を 10 倍した 10 を 7 で割ると、1 と余り 3 を得る。

7 で割った解が 1、4、2、8、5、7(赤字)と続き、次の 1(青字) からは、同じ計算が繰り返されることが分かります。

いくつかの数字について計算をすると、以下のことが分かります。

  • $d$ で割った解の周期は、長くても $d – 1$ である。
    これは、$d$ で割った余りが、0 から $d – 1$ までしかなく、0 の場合は割り切れているためです(余りが 1 から $d – 1$ までしかないため、どこかで同じ余りが出現する)。
  • $d$ の素因数が 2 もしくは 5 だけから成る場合だけ割り切れる。

振り返った計算を関数 calc_recurring_cycle として実装して、問題を解きました。この関数を汎用的に実装するため C99 で仕様追加された可変長配列を使っています(配列 remain_pos)。

#include <stdio.h>

int calc_recurring_cycle(int number)
{
	int i;
	int remain_pos[number];
	int remain;
	int pos;
	int answer = 0;

	for (i = 0; i < number; ++i) {
		remain_pos[i] = 0;
	}

	remain = 1;
	pos = 1;
	while (pos <= number) {
		remain = (remain * 10)% number;
		if (remain == 0) {
			answer = 0;
			break;
		} else if (remain_pos[remain] != 0) {
			answer = pos - remain_pos[remain];
			break;
		} else {
			remain_pos[remain] = pos;
		}
		++pos;
	}

	return answer;
}

int main(void)
{
	int i;
	int cycle;
	int max_i = 0;
	int max_cycle = 0;

	for (i = 2; i < 1000; ++i) {
		cycle = calc_recurring_cycle(i);
		if (cycle > max_cycle) {
			max_i = i;
			max_cycle = cycle;
		}
	}

	printf("Problem026: %d\n", max_i);

	return 0;
}

実験

この問題の答えは 1000 に近い数字となります。調べてみると、周期は $d -1$ になっていました。

前述したように $1/d$ の周期は、長くても $d – 1$ となります。そのような $d$ がいくつあるか調べてみました。

d 未満 d – 1 の周期を持つ d の個数割合(%)
10111.11%
10099.09%
1000606.01%
100004674.67%

10 未満の個数が 1 とあるのは 7(周期 6)です。周期が $d – 1$ になる数は、もっと少なくなると考えていましたが、思ったより減っていません。参考までに 1万未満で周期が $d – 1$ となる一番大きな数は、9967 でした。

最後に

割り算による周期性は、例を示せば子供でも理解できるかもしれません。一方、数字を大きくすると手で計算するのが難しくなります。プログラミングができると、このような場合に、すぐに実験ができます。数学やコンピュータに興味を持つ人が増えていき、このような実験の延長で、偉大な定理証明がされることが起こるかもしれません。

Project Euler の問題を25問解いてレベル1になりました。レベル2となる問題50まで、ぼちぼちと紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA