鱼C论坛

 找回密码
 立即注册
查看: 4197|回复: 11

题目64:10000以下的连分数中有多少拥有奇数周期?

[复制链接]
发表于 2015-8-7 22:14:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 永恒的蓝色梦想 于 2020-6-5 13:30 编辑
Odd period square roots

All square roots are periodic when written as continued fractions and can be written in the form:

QQ20150807-3@2x.png

For example, let us consider QQ20150807-8@2x.png :

QQ20150807-4@2x.png

If we continue we would get the following expansion:

QQ20150807-5@2x.png

The process can be summarised as follows:

QQ20150807-6@2x.png

It can be seen that the sequence is repeating. For conciseness, we use the notation QQ20150807-9@2x.png , to indicate that the block (1,3,1,8) repeats indefinitely.

The first ten continued fraction representations of (irrational) square roots are:

QQ20150807-7@2x.png

Exactly four continued fractions, for N ≤ 13, have an odd period.

How many continued fractions for N ≤ 10000 have an odd period?

题目:

所有的平方根写作连分数的时候都是周期性的,并且可以写成如下形式:

QQ20150807-3@2x.png

例如 QQ20150807-8@2x.png :

QQ20150807-4@2x.png

如果继续下去我们得到如下展开式:

QQ20150807-5@2x.png

这个过程可以被总结如下:

QQ20150807-6@2x.png

可以看出这个序列是重复的。简明起见,我们用 QQ20150807-9@2x.png , 来表示 (1,3,1,8) 这个部分不断重复出现。

前十个无理平方根的连续分数表示为:

√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, 有四个连分数的周期是奇数。

对于 N ≤ 10000,有多少连分数的周期是奇数?

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2015-8-8 11:16:01 | 显示全部楼层
刚刚开始学习,看着好厉害的样子:lol:
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-31 16:00:32 | 显示全部楼层
mark下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-14 17:30:41 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2016-10-14 21:22 编辑

这题的思路就是找出除整数部分后面的无理数从第几位开始循环。
a是整数部分+无理数部分,d是整数部分,c就是无理数部分。
依次存入列表,然后比较。开始循环了就记录下来。
代码如下:

  1. import math
  2. def gao(n):
  3.         m = int(math.sqrt(n))
  4.         if m * m == n:
  5.                 return 0
  6.         dic = {}
  7.         d = m
  8.         a = n
  9.         b = -m
  10.         c = 1
  11.         len = 0
  12.         while True:
  13.                 nc =  a - b * b
  14.                 nc /= c
  15.                 nd = int((math.sqrt(a) - b) / nc)
  16.                 nb = -b - nd * nc
  17.                 t = (nb, nc, nd)
  18.                 b = nb
  19.                 c = nc
  20.                 d = nd
  21.                 if not t in dic:
  22.                         len += 1
  23.                         dic[t] = 1
  24.                 else:
  25.                         break
  26.                        
  27.         return len
  28. ans = 0
  29. for i in range(1, 10001):
  30.         k = gao(i)
  31.         if k % 2 != 0:
  32.                 ans += 1
  33. print (ans)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-14 20:41:06 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2016-10-14 21:22 编辑

结果1322
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-16 21:56:30 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2016-10-16 22:17 编辑

另外一个暴力的的方法,用decimal库,把精度提高到250位以上(200位小数,仍有3个数有误差)
同样可以得到结果......1322......7秒多,速度也还行,简单粗暴,不用考虑复杂的数学方程式
  1. import decimal as dc
  2. dc.getcontext().prec = 250
  3. def root(n):
  4.     blist = []
  5.     n0 = dc.Decimal(i).sqrt()
  6.     a0 = int(n0)
  7.     b0 = n0 - a0
  8.     n1 = 1/b0
  9.     a1 = int(n1)
  10.     b1 = n1 - a1
  11.     while str(b1)[:11] not in blist:
  12.         blist.append(str(b1)[:11])
  13.         n1 = 1/b1
  14.         a1 = int(n1)
  15.         b1 = n1 - a1
  16.     return len(blist)

  17. count = 0
  18. for i in range(2,10000):
  19.     if i**0.5 != int(i**0.5):
  20.         if root(i) % 2 == 1:
  21.             count += 1
  22. print (count)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-3 00:03:54 | 显示全部楼层
用的matlab
浮点数真是头疼,
    1322      

时间已过 0.413237 秒。
>>
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-12-14 22:39:06 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-2-20 13:18 编辑

C++ 43ms
  1. #include<iostream>
  2. #include<unordered_map>
  3. #include<cmath>



  4. constexpr int gcd(int a, int b, int c)noexcept {
  5.     int t = 0;

  6.     while (b) {
  7.         t = a % b;
  8.         a = b;
  9.         b = t;
  10.     }

  11.     while (c) {
  12.         t = a % c;
  13.         a = c;
  14.         c = t;
  15.     }

  16.     return a;
  17. }



  18. struct Quad {
  19.     //(a * sqrt(b) + c) / d
  20.     const short a, b, c, d;
  21. };



  22. int main() {
  23.     using namespace std;
  24.     ios::sync_with_stdio(false);

  25.     short temp, a, b, c, d, sqrt_of_b;
  26.     unsigned int* ptr;
  27.     unsigned int count = 0, index;
  28.     double sqrt_;
  29.     unordered_map<size_t, unsigned int> indecies;


  30.     for (b = 1; b <= 10000; b++) {
  31.         sqrt_ = sqrt(b);

  32.         if (fmod(sqrt_, 1.0)) {
  33.             sqrt_of_b = sqrt_;
  34.             a = d = 1;
  35.             c = -sqrt_of_b;

  36.             for (index = 1;; index++) {
  37.                 ptr = &indecies[*(unsigned long long*)(&Quad{a, b, c, d})];

  38.                 if (*ptr) {
  39.                     count += (index - *ptr) & 1;
  40.                     indecies.clear();
  41.                     break;
  42.                 }

  43.                 *ptr = index;

  44.                 temp = a * a * b - c * c;
  45.                 a *= d;
  46.                 c *= -d;
  47.                 d = temp;

  48.                 temp = gcd(a, c, d);
  49.                 a /= temp;
  50.                 c /= temp;
  51.                 d /= temp;
  52.                 c -= (sqrt_of_b * a + c) / d * d;
  53.             }
  54.         }
  55.     }


  56.     cout << count << endl;
  57.     return 0;
  58. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-17 18:04:14 | 显示全部楼层
和求无限小数的循环节问题很像
1322
  1. #include<iostream>
  2. #include<cmath>
  3. #include<algorithm>
  4. using namespace std;

  5. int sq[100] = {0};  //平方数表

  6. void init(){    //打平方数表
  7.     for (int i = 2; i <= 101; i++)  sq[i-2] = i*i;
  8. }

  9. bool issquare(int n){   //判断平方数
  10.     if (binary_search(sq, sq+100, n)) return true;
  11.     return false;
  12. }

  13. int gcd(int x, int y){
  14.     if (x % y == 0) return y;
  15.     return gcd(y, x % y);
  16. }

  17. int period(int n){
  18.     int deno = 1;   //分母
  19.     int cons = -(int)sqrt(n);   //小数部分的有理项系数
  20.    
  21.     int kount = 0;
  22.     do  //模拟手算过程
  23.     {
  24.         int t = n - cons*cons;
  25.         double revert = deno / (sqrt(n) + cons);
  26.         
  27.         deno = t / gcd(t, deno);
  28.         cons = (int) floor( ((revert - (int)revert) * deno - sqrt(n) + 0.5));
  29.         
  30.         kount++;
  31.     } while (deno != 1);
  32.     return kount;
  33. }

  34. int main(int argc, char const *argv[])
  35. {
  36.     init();
  37.     int kount = 0;
  38.     for (int n = 2; n <= 10000; n++){
  39.         if (issquare(n))    continue;   //平方数不循环
  40.         if (period(n) % 2 == 1) kount++;
  41.     }
  42.     cout << kount << endl;
  43.     getchar();
  44.     return 0;
  45. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-10 19:12:54 | 显示全部楼层
  1. /*
  2. 答案:1322
  3. 耗时:0.0162126秒(单核)
  4.       0.0035869秒(六核)
  5. */
  6. #include <iostream>
  7. #include <vector>
  8. #include <algorithm>
  9. #include <string>
  10. #include <cmath>
  11. #include <omp.h>
  12. using namespace std;

  13. int gcd(int x, int y)//计算x,y的最大公因数
  14. {
  15.   if (y == 0)
  16.     return x;
  17.   int z = x % y;
  18.   while (z != 0)
  19.   {
  20.     x = y;
  21.     y = z;
  22.     z = x % y;
  23.   }
  24.   if (y < 0)
  25.     return (-y);
  26.   return y;
  27. }

  28. struct stItem //对应分式 (a*sqrt(D)+b)/c,d=sqrt(D)
  29. {
  30.   int a, b, c;
  31.   stItem(void)
  32.   {
  33.     a = 0;
  34.     b = 0;
  35.     c = 1;
  36.   }
  37.   stItem(int x, int y, int z)
  38.   {
  39.     c = gcd(x, y);
  40.     c = gcd(c, z);
  41.     a = x / c;
  42.     b = y / c;
  43.     c = z / c;
  44.   }
  45.   stItem(const stItem& x)
  46.   {
  47.     memcpy_s(this, sizeof(stItem), &x, sizeof(stItem));
  48.   }
  49.   const stItem& operator=(const stItem& x)
  50.   {
  51.     memcpy_s(this, sizeof(stItem), &x, sizeof(stItem));
  52.     return *this;
  53.   }
  54.   bool operator==(const stItem& x) const
  55.   {
  56.     return (a == x.a && b == x.b && c == x.c);
  57.   }
  58. };

  59. /*
  60. 返回0还没有找到周期,否则就是周期的长度
  61. a,b,c进入时为本次的三元组,返回时是下次的三元组
  62. vItems 记录三元组,用于查找周期
  63. */
  64. int f(int nD, int rt, int& a, int& b, int& c, vector<stItem>& vItems)
  65. {
  66.   int q = int((a * rt + b) / c);
  67.   int a1 = a * c;
  68.   int b1 = c * (c * q - b);
  69.   int c1 = a * a * nD - (c * q - b) * (c * q - b);
  70.   stItem it(a1, b1, c1);
  71.   a = it.a;
  72.   b = it.b;
  73.   c = it.c;
  74.   vector<stItem>::iterator itr = find(vItems.begin(), vItems.end(), it);
  75.   if (itr == vItems.end())
  76.   {
  77.     vItems.push_back(it);
  78.     return 0;
  79.   }
  80.   return int(vItems.end() - itr);
  81. }

  82. int main(void)
  83. {
  84.   double t = omp_get_wtime();
  85.   int nCount = 0;
  86. #pragma omp parallel for reduction(+:nCount)
  87.   for (int i = 2; i <= 10000; ++i)
  88.   {
  89.     int j = int(sqrt(double(i)));
  90.     if (j * j == i)
  91.       continue;
  92.     vector<stItem> vItems;
  93.     int a = 1, b = 0, c = 1;//刚开始只有sqrt(i)
  94.     stItem it(a, b, c);
  95.     vItems.push_back(it);
  96.     while (true)//展开sqrt(i)
  97.     {
  98.       int k = f(i, j, a, b, c, vItems);
  99.       if (k > 0)//直到出现周期
  100.       {
  101.         nCount += (k & 1);//计数奇数周期
  102.         break;
  103.       }
  104.     }
  105.   }
  106.   t = omp_get_wtime() - t;
  107.   cout << nCount << endl << t << endl;
  108.   return 0;
  109. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-29 21:30:51 | 显示全部楼层
  1. import time as t
  2. import decimal as dc

  3. start = t.perf_counter()
  4. count = 0
  5. dc.getcontext().prec = 250
  6. num_list = [n for n in range(10001)]
  7. nums = []
  8. for n in range(101):
  9.     num_list.remove(n ** 2)
  10. for n in num_list:
  11.     radicand = dc.Decimal(n).sqrt()
  12.     first_num = int(radicand)
  13.     decimal_list = [first_num]
  14.     while True:
  15.         radicand = dc.Decimal(1) / dc.Decimal(radicand - int(radicand))
  16.         if str(radicand)[:11] not in decimal_list:
  17.             decimal_list.append(str(radicand)[:11])
  18.         else:
  19.             len_decimal = len(decimal_list)
  20.             if (len_decimal - decimal_list.index(str(radicand)[:11])) % 2:
  21.                 count += 1
  22.             break

  23. print(count)
  24. print("It costs %f s" % (t.perf_counter() - start))
复制代码


1322
It costs 2.698963 s
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-2-27 19:58:31 | 显示全部楼层
本帖最后由 TLM 于 2023-2-27 20:20 编辑

不使用浮点数开方进行求解
python
1322
Time:1.935354232788086s
但问题的关键是为什么一次取整之后,就可以循环了
  1. import time
  2. st=time.time()
  3. def getGYS(u,v):
  4.     # 获取公约数
  5.     if u<v:
  6.         u,v=v,u
  7.     while v>0:
  8.         u,v=v,u%v
  9.     return u
  10. def get(N,a0=1):
  11.     ans=[]
  12.     # 第一次取整
  13.     while (a0+1)**2<N:
  14.         a0=a0+1
  15.     if (a0+1)**2==N:
  16.         return [a0+1],a0
  17.     ans.append(a0)
  18.     a1=-a0
  19.     a2=N-a0**2
  20.     a0=1
  21.     chushi=(a0,a1,a2)
  22.     while True:
  23.         # 循环取整
  24.         '''
  25.         a3<(a0√N-a1)/a2<a3+1
  26.         转化为(a3*a2+a1)**2<a0**2*N<((a3+1)*a2+a1)**2
  27.         获取a3
  28.         '''
  29.         a3=0
  30.         while ((a3+1)*a2+a1)**2<a0**2*N:
  31.             a3=a3+1
  32.         ans.append(a3)
  33.         # 重新转化为(a0√N-a1)/a2的形式
  34.         a0,a1,a2=a2*a0,-a2*a0*(a1+a2*a3),a0**2*N-(a1+a2*a3)**2
  35.         gys=getGYS(a2,a0)
  36.         a0,a1,a2=a0//gys,a1//gys,a2//gys
  37.         if (a0,a1,a2)==chushi:
  38.             return ans,a0
  39. # N=13
  40. # print(get(N))
  41. n=0
  42. N=10000
  43. a0=1
  44. for i in range(2,N+1):
  45.     ans,a0=get(i,a0)
  46.     if len(ans)%2==0:
  47.         n=n+1
  48. print(n)
  49. print('Time:{}s'.format(time.time()-st))
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 16:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表