Problem 64
Odd period square roots
All square roots are periodic when written as continued fractions and can be written in the form:
For example, let us consider √23:
If we continue we would get the following expansion:
The process can be summarised as follows:
It can be seen that the sequence is repeating. For conciseness, we use the notation √23 = [4;(1,3,1,8)], to indicate that the block (1,3,1,8) repeats indefinitely.
The first ten continued fraction representations of (irrational) square roots are:
√2=[1;(2)], period=1
√3=[1;(1,2)], period=2
√5=[2;(4)], period=1
√6=[2;(2,4)], period=2
√7=[2;(1,1,1,4)], period=4
√8=[2;(1,4)], period=2
√10=[3;(6)], period=1
√11=[3;(3,6)], period=2
√12= [3;(2,6)], period=2
√13=[3;(1,1,1,1,6)], period=5
Exactly four continued fractions, for N ≤ 13, have an odd period.
How many continued fractions for N ≤ 10000 have an odd period?
奇周期平方根
所有的平方根写成如下连分数表示时都是周期性重复的:
例如,让我们考虑√23:
如果我们继续这个过程,我们会得到如下的展开:
这个过程可以总结如下:
可以看出序列正在重复。我们将其简记为√23 = [4;(1,3,1,8)],表示在此之后(1,3,1,8)无限循环。
前10个(无理数)平方根的连分数表示是:
√2=[1;(2)],周期=1
√3=[1;(1,2)],周期=2
√5=[2;(4)],周期=1
√6=[2;(2,4)],周期=2
√7=[2;(1,1,1,4)],周期=4
√8=[2;(1,4)],周期=2
√10=[3;(6)],周期=1
√11=[3;(3,6)],周期=2
√12= [3;(2,6)],周期=2
√13=[3;(1,1,1,1,6)],周期=5
在N ≤ 13中,恰好有4个连分数表示的周期是奇数。
在N ≤ 10000中,有多少个连分数表示的周期是奇数?
package cuppics;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
public class Prj64 extends TestCase {
public void testOddPeriodSquareRoots() {
int count = 0;
for (int i = 2; i <= 10000; i++) {
List<Integer> data = getCircle(i);
if( data.size() % 2 == 1){
count ++;
}
}
String fstr = "numOf odd period=%d" ;
fstr = String.format(fstr, count);
System.out.println(fstr);
}
/**
* https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#
* Continued_fraction_expansion
*/
public List<Integer> getCircle(int S) {
int val = (int) Math.sqrt(S);
//square
if (val * val == S) {
return new ArrayList<Integer>();
}
List<Integer> ret = new ArrayList<Integer>();
int m0 = 0;
int d0 = 1;
int a0 = (int) Math.floor(Math.sqrt(S));
int _a0 = a0;
int mn = 0;
int dn = 0;
int an = 0;
while (true) {
mn = d0 * a0 - m0;
dn = (S - mn * mn) / d0;
an = (int) Math.floor((_a0 + mn) / dn);
m0 = mn;
d0 = dn;
a0 = an;
ret.add(a0);
if (an == 2 * _a0) {
break;
}
}
return ret;
}
}