欧拉计划 Project Euler64(奇周期平方根)题解
欧拉计划 Project Euler 64题解
- 题干
- 奇数平方根
- 思路
- 连分数展开算法
- code
题干
奇数平方根
所有的平方根写成如下连分数表示时都是周期性重复的:
N = a 0 + 1 a 1 + 1 a 2 + 1 a 3 + … \sqrt{N}=a_0+\frac 1 {a_1+\frac 1 {a_2+ \frac 1 {a_3+ \dots}}} N=a0+a1+a2+a3+…111
例如,让我们考虑 23 \sqrt{23} 23
23 = 4 + 23 − 4 = 4 + 1 1 23 − 4 = 4 + 1 1 + 23 − 3 7 \quad \quad \sqrt{23}=4+\sqrt{23}-4=4+\frac 1 {\frac 1 {\sqrt{23}-4}}=4+\frac 1 {1+\frac{\sqrt{23}-3}7} 23=4+23−4=4+23−411=4+1+723−31
如果我们继续展开,会得到:
23 = 4 + 1 1 + 1 3 + 1 1 + 1 8 + … \sqrt{23}=4+\frac 1 {1+\frac 1 {3+ \frac 1 {1+\frac 1 {8+ \dots}}}} 23=4+1+3+1+8+…1111
这个过程可以总结如下:
a 0 = 4 , 1 23 − 4 = 23 + 4 7 = 1 + 23 − 3 7 \quad \quad a_0=4, \frac 1 {\sqrt{23}-4}=\frac {\sqrt{23}+4} 7=1+\frac {\sqrt{23}-3} 7 a0=4,23−41=723+4=1+723−3
a 1 = 1 , 7 23 − 3 = 7 ( 23 + 3 ) 14 = 3 + 23 − 3 2 \quad \quad a_1=1, \frac 7 {\sqrt{23}-3}=\frac {7(\sqrt{23}+3)} {14}=3+\frac {\sqrt{23}-3} 2 a1=1,23−37=147(23+3)=3+223−3
a 2 = 3 , 2 23 − 3 = 2 ( 23 + 3 ) 14 = 1 + 23 − 4 7 \quad \quad a_2=3, \frac 2 {\sqrt{23}-3}=\frac {2(\sqrt{23}+3)} {14}=1+\frac {\sqrt{23}-4} 7 a2=3,23−32=142(23+3)=1+723−4
a 3 = 1 , 7 23 − 4 = 7 ( 23 + 4 ) 7 = 8 + 23 − 4 \quad \quad a_3=1, \frac 7 {\sqrt{23}-4}=\frac {7(\sqrt{23}+4)} 7=8+\sqrt{23}-4 a3=1,23−47=77(23+4)=8+23−4
a 4 = 8 , 1 23 − 4 = 23 + 4 7 = 1 + 23 − 3 7 \quad \quad a_4=8, \frac 1 {\sqrt{23}-4}=\frac {\sqrt{23}+4} 7=1+\frac {\sqrt{23}-3} 7 a4=8,23−41=723+4=1+723−3
a 5 = 1 , 7 23 − 3 = 7 ( 23 + 3 ) 14 = 3 + 23 − 3 2 \quad \quad a_5=1, \frac 7 {\sqrt{23}-3}=\frac {7 (\sqrt{23}+3)} {14}=3+\frac {\sqrt{23}-3} 2 a5=1,23−37=147(23+3)=3+223−3
a 6 = 3 , 2 23 − 3 = 2 ( 23 + 3 ) 14 = 1 + 23 − 4 7 \quad \quad a_6=3, \frac 2 {\sqrt{23}-3}=\frac {2(\sqrt{23}+3)} {14}=1+\frac {\sqrt{23}-4} 7 a6=3,23−32=142(23+3)=1+723−4
a 7 = 1 , 7 23 − 4 = 7 ( 23 + 4 ) 7 = 8 + 23 − 4 \quad \quad a_7=1, \frac 7 {\sqrt{23}-4}=\frac {7(\sqrt{23}+4)} {7}=8+\sqrt{23}-4 a7=1,23−47=77(23+4)=8+23−4
可以看出序列正在重复。我们将其简记为 23 = [ 4 ; ( 1 , 3 , 1 , 8 ) ] \sqrt{23}=[4;(1,3,1,8)] 23=[4;(1,3,1,8)],表示 ( 1 , 3 , 1 , 8 ) (1,3,1,8) (1,3,1,8)在此之后无限循环。
前 10 10 10个(无理数)平方根的连分数表示是:
2 = [ 1 ; ( 2 ) ] \quad \quad \sqrt{2}=[1;(2)] 2=[1;(2)],周期为 1 1 1
3 = [ 1 ; ( 1 , 2 ) ] \quad \quad \sqrt{3}=[1;(1,2)] 3=[1;(1,2)], 周期为 2 2 2
5 = [ 2 ; ( 4 ) ] \quad \quad \sqrt{5}=[2;(4)] 5=[2;(4)], 周期为 1 1 1
6 = [ 2 ; ( 2 , 4 ) ] \quad \quad \sqrt{6}=[2;(2,4)] 6=[2;(2,4)], 周期为 2 2 2
7 = [ 2 ; ( 1 , 1 , 1 , 4 ) ] \quad \quad \sqrt{7}=[2;(1,1,1,4)] 7=[2;(1,1,1,4)], 周期为 4 4 4
8 = [ 2 ; ( 1 , 4 ) ] \quad \quad \sqrt{8}=[2;(1,4)] 8=[2;(1,4)], 周期为 2 2 2
10 = [ 3 ; ( 6 ) ] \quad \quad \sqrt{10}=[3;(6)] 10=[3;(6)],周期为 1 1 1
11 = [ 3 ; ( 3 , 6 ) ] \quad \quad \sqrt{11}=[3;(3,6)] 11=[3;(3,6)], 周期为 2 2 2
12 = [ 3 ; ( 2 , 6 ) ] \quad \quad \sqrt{12}=[3;(2,6)] 12=[3;(2,6)], 周期为 2 2 2
13 = [ 3 ; ( 1 , 1 , 1 , 1 , 6 ) ] \quad \quad \sqrt{13}=[3;(1,1,1,1,6)] 13=[3;(1,1,1,1,6)], 周期为 5 5 5
在 N ≤ 13 N\leq13 N≤13中,恰好有 4 4 4个连分数表示的周期是奇数。
在 N ≤ 10000 N\leq10000 N≤10000中,有多少个连分数表示的周期是奇数?
思路
我们需要找出 N ≤ 10000 N \leq 10000 N≤10000的范围内,有多少个整数 N N N使得其平方根 N \sqrt{N} N的连分数表示的周期长度是奇数。我们只考虑 N N N不是完全平方数的情况,因为完全平方数的平方根是整数(有理数),其连分数表示是有限的,没有周期。
连分数展开算法
求 N \sqrt{N} N的连分数表示 [ a 0 : ( a 1 , a 2 , … , a p ) ] [a_{0}:(a_{1},a_{2}, \dots,a_{p})] [a0:(a1,a2,…,ap)]的标准算法如下:
- 令 x 0 = N x_{0} = \sqrt{N} x0=N
- 计算 a 0 = ⌊ x 0 ⌋ = ⌊ N ⌋ a_{0} = \lfloor x_{0} \rfloor = \lfloor \sqrt{N} \rfloor a0=⌊x0⌋=⌊N⌋
- 我们寻找一种形式 ξ k = N + m k d k \xi_{k} = \frac{\sqrt{N}+m_{k}}{d_{k}} ξk=dkN+mk,其中 m k , d k m_{k}, d_{k} mk,dk是整数
- 初始状态: m 0 = 0 , d 0 = 1 m_{0} = 0, d_{0} = 1 m0=0,d0=1
- 迭代计算 a k , m k + 1 , d k + 1 ( k ≥ 0 ) a_{k}, m_{k + 1}, d_{k + 1}(k \geq 0) ak,mk+1,dk+1(k≥0):
- a k = ⌊ N + m k d k ⌋ = ⌊ a 0 + m k d k ⌋ a_{k} = \lfloor \frac{\sqrt{N}+m_{k}}{d_{k}} \rfloor = \lfloor \frac{a_{0} + m_{k}}{d_{k}} \rfloor ak=⌊dkN+mk⌋=⌊dka0+mk⌋
- m k + 1 = d k a k − m k m_{k + 1} = d_{k}a_{k} - m_{k} mk+1=dkak−mk
- d k + 1 = N − m k + 1 2 d k d_{k + 1} = \frac{N - m_{k + 1}^{2}}{d_{k}} dk+1=dkN−mk+12
- 这个序列 a 1 , a 2 , … a_{1}, a_{2}, \dots a1,a2,…是周期性的,周期从 a 1 a_{1} a1开始
- 当 a k = 2 a 0 a_{k} = 2a_{0} ak=2a0时,达到周期的最后一个元素 a p a_{p} ap,此时的 k k k就是周期长度 p p p
code
// 1322
#include <bits/stdc++.h>using namespace std;using ll = long long;void solve() {int li = 10000;int ans = 0;for (int N = 2; N <= li; ++N) {int a0 = static_cast<int>(sqrt(N));if (a0 * a0 == N) continue; // 完全平方数直接跳过即可int p = 0; // 周期长度// 第一轮参数 对应 m1 d1 a1int m = a0;int d = N - m * m;int a = static_cast<int>(floor((double)(a0 + m) / d));while (a != 2 * a0) {m = d * a - m;d = (N - m * m) / d;a = static_cast<int>(floor((double)(a0 + m) / d));p++;}p++;if (p % 2) {ans++;}}cout << ans << "\n";
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int tt = 1; // cin >> tt;while (tt--) {solve();}return 0;
}