Problem 64 : Odd period square roots
All square roots are periodic when written as continued fractions and can be written in the form:
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?
C++代码
#include <iostream>
#include <vector>
#include <iterator>
#include <cmath>
#include <cassert>
using namespace std;
//#define UNIT_TEST
class PE0064
{
private:
int getPeriod(int N);
public:
int getNumOfContinuedFractions(int maxN);
};
int PE0064::getPeriod(int N)
{
#ifdef UNIT_TEST
vector<int>fractions_vec;
#endif
int period = 0;
int m = 0, d = 1;
double root = sqrt((double)N);
int a0 = int(root);
int a = a0;
#ifdef UNIT_TEST
fractions_vec.push_back(a0);
// cout << "m=" << m << ", d=" << d << ", a=" << a << endl;
#endif
while (a != 2*a0)
{
m = a*d - m;
d = (N - m*m) / d;
a = int((root + m) / d);
period++;
#ifdef UNIT_TEST
fractions_vec.push_back(a);
//cout << "m=" << m << ", d=" << d << ", a=" << a << endl;
#endif
}
#ifdef UNIT_TEST
cout << "√" << N << " = [" << fractions_vec[0] << "; (" ;
copy(fractions_vec.begin()+1, fractions_vec.end()-1,
ostream_iterator<int>(cout, ","));
int size = fractions_vec.size();
cout << fractions_vec[size-1] << ")], period = " << period << endl;
#endif
return period;
}
int PE0064::getNumOfContinuedFractions(int maxN)
{
int numOfContinuedFractions = 0;
for (int N=2; N<=maxN; N++)
{
int root = (int)sqrt(double(N));;
if (root*root == N)
{
continue;
}
else
{
if (getPeriod(N) % 2 == 1)
{
numOfContinuedFractions ++;
}
}
}
return numOfContinuedFractions;
}
int main()
{
PE0064 pe0064;
assert(4 == pe0064.getNumOfContinuedFractions(13));
cout << pe0064.getNumOfContinuedFractions(10000);
cout << " continued fractions for N<=10000 have an odd period." << endl;
return 0;
}
Python代码
def getPeriod(N):
global Enable_Debug
period, m, d = 0, 0, 1
root = int(N**0.5)
a0, a = root, root
fractions_list = [ a0 ]
#print("m=", m, ", d=", d, ", a=", a)
while a != 2*a0:
m = a*d - m
d = (N - m*m) / d
a = int((root + m) / d)
period += 1
fractions_list += [ a ]
#print("m=", m, ", d=", d, ", a=", a)
if True == Enable_Debug:
print("√%d"% N, "= [%d" % fractions_list[0], "; (", end='')
for f in fractions_list:
if f != fractions_list[-1]:
print("%d, " %f, end='')
else:
print("%d" %f, end='')
print(")], period = %d" % period)
return period
def getNumOfContinuedFractions(maxN):
numOfContinuedFractions = 0
for N in range(2, maxN+1):
root = int(N**0.5)
if root*root == N:
continue
else:
if 1 == getPeriod(N) % 2:
numOfContinuedFractions += 1
return numOfContinuedFractions
def main():
global Enable_Debug
Enable_Debug = True
assert 4 == getNumOfContinuedFractions(13)
Enable_Debug = False
print(getNumOfContinuedFractions(10000), end=' ')
print("continued fractions for N<=10000 have an odd period.")
if __name__ == '__main__':
main()
Python 代码(类的实现)
class PE0064(object):
def __init__(self):
self.Enable_Debug = True
def getPeriod(self, N):
period, m, d = 0, 0, 1
root = int(N**0.5)
a0, a = root, root
fractions_list = [ a0 ]
#print("m=", m, ", d=", d, ", a=", a)
while a != 2*a0:
m = a*d - m
d = (N - m*m) / d
a = int((root + m) / d)
period += 1
fractions_list += [ a ]
#print("m=", m, ", d=", d, ", a=", a)
if True == self.Enable_Debug:
print("√%d"% N, "= [%d" % fractions_list[0], "; (", end='')
for f in fractions_list:
if f != fractions_list[-1]:
print("%d, " %f, end='')
else:
print("%d" %f, end='')
print(")], period = %d" % period)
return period
def getNumOfContinuedFractions(self, maxN):
numOfContinuedFractions = 0
for N in range(2, maxN+1):
root = int(N**0.5)
if root*root == N:
continue
else:
if 1 == self.getPeriod(N) % 2:
numOfContinuedFractions += 1
return numOfContinuedFractions
def main():
pe0064 = PE0064()
assert 4 == pe0064.getNumOfContinuedFractions(13)
pe0064.Enable_Debug = False
print(pe0064.getNumOfContinuedFractions(10000), end=' ')
print("continued fractions for N<=10000 have an odd period.")
if __name__ == '__main__':
main()