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.166666... という数字であり、6が循環節であることを表している。1/7 循環節は6桁ある。 d < 1000 なる 1/d の中で循環節が最も長くなるような d を求めよ。
A = Table[ Length[ RealDigits[1/i][[1, 1]] ] , {i, 1000} ]; Position[A, Max[A]]
IntegerDigitsと同じように、RealDigitsは整数の桁のリストと小数点の位置を返します。
例えば RealDigits[12.345] の場合、 {{1, 2, 3, 4, 5}, 2}
となります。
ここまではIntegerDigitsとなんらかわりない機能のように思えますが、RealDigitsは、例えばある循環小数、
RealDigits[1/7]
を実行すると
{{1, 4, 2, 8, 5, 7}}, 0}
のように、循環する部分のみを返してくるというチートのような機能を有しています。
この桁数を数えて全部足せばいいわけです。楽!
C/C++
#include <iostream> using namespace std; // n/d の循環小数を求め、循環節の長さを返す。 // aの大きさはd以上である必要があります int repDecimal(int n, int d){ int a[1000], q, r; for(int i=0 ; i<1000 ; i++){ a[i] = 0; } q = n/d; r = n - q*d; //cout << n << " / " << d << " = " << q << "."; int i=0; // 余りがゼロになるまで繰り返す while(r != 0){ n = r * 10; q = n/d; r = n - q*d; if (a[r] == 1){ // 循環したとき //cout << "..."; break; } i++; a[r]++; //cout << q; } //cout << endl; return i; } int main(void) { int k, length=0, ans; for(int i=1 ; i<1000 ; i++){ k = repDecimal(1,i); if( length < k){ length = k; ans = i; } } cout << ans << endl; int end; cin >> end; }
同じ余りが出てきたら循環している、という発想がでてからはすぐでした。