找回密码
 注册
Simdroid-非首页
查看: 245|回复: 7

[欧拉习题] ProjEuler[39]:找勾股数

[复制链接]
发表于 2009-12-14 18:15:28 | 显示全部楼层 |阅读模式 来自 甘肃兰州
If p is the perimeter of a right angle triangle with integral length sides, {a,b,c}, there are exactly three solutions for p = 120.

{20,48,52}, {24,45,51}, {30,40,50}

For which value of p ≤ 1000, is the number of solutions maximised?

120可以写为三组勾股数(整数)之和,分别是{20,48,52}, {24,45,51}, {30,40,50}。要求在不超过1000的数字中求出可以写为最多组勾股数之和的数。
 楼主| 发表于 2009-12-14 18:17:33 | 显示全部楼层 来自 甘肃兰州
Simdroid开发平台
  1. Timing[data = Range[500]^2;
  2. lis = {};
  3. For[m = 2, m < 500, m++,
  4.   For[n = 2, n <= m, n++,
  5.    If[MemberQ[data, data[[m]] + data[[n]]],
  6.     lis = Append[lis, {m, n, Sqrt[m^2 + n^2]}]]]];
  7. Total /@ lis // Commonest]
复制代码
要算10秒左右。感觉不是很好。找勾股数有什么好办法?
回复 不支持

使用道具 举报

发表于 2009-12-14 20:29:06 | 显示全部楼层 来自 上海宝山区
My notebook should be faster.

本帖子中包含更多资源

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

×
回复 不支持

使用道具 举报

发表于 2009-12-16 18:42:13 | 显示全部楼层 来自 上海徐汇区
  1. f[lim_] := Module[{m = 1, n = 2, lis = {}},
  2. While[m <= Floor[lim/3],
  3. While[n <= Floor[(lim - m)/2],
  4. If[IntegerQ[Sqrt[m^2 + n^2]] && m + n + Sqrt[m^2 + n^2] <= lim,
  5. AppendTo[lis, m + n + Sqrt[m^2 + n^2]]];
  6. n++;];
  7. m++; n = m + 1];
  8. lis // Commonest]
复制代码


  1. Timing[f[1000]]
复制代码


试试看~

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2010-4-27 14:15:54 | 显示全部楼层 来自 河南郑州
本帖最后由 chyanog 于 2013-5-21 19:52 编辑

本来想能不用Reduce就不用,由于它不够“底层”,不过的确强大。下面两种做法都用到了Reduce,其中第二个效率不错,当范围增大时尤为明显。

  1. Timing[sol =
  2.   Reduce[3 < x + y + z <= 1000 && x^2 + y^2 == z^2 && x > 0 && y > 0 &&
  3.      z > 0, {x, y, z}, Integers];
  4. x + y + z //. (Cases[sol, Except[False]] /. {And -> List, Or -> List,
  5.        Equal -> Rule}) // Commonest]
复制代码
{7.156, {840}}

  1. Timing[GGS[max_] := Module[{x, y, r,s},
  2.    r = Table[
  3.      Reduce[x^2 + y^2 == z^2 && 0 < x <y <= max, {x, y},
  4.       Integers], {z, max}];
  5.    s = {x, y} /.
  6.       DeleteCases[r /. {And -> List, Or -> List, Equal -> Rule},
  7.        False];
  8.    Sort@Partition[Flatten[s], 2] /. {x_, y_} -> {x, y, Sqrt[x^2 + y^2]}
  9.    ];
  10. Commonest[Tr /@ GGS[500]]]
复制代码
{1.578, {840}}

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2010-7-13 16:03:53 | 显示全部楼层 来自 北京
问题的瓶颈在于如何记录已经发现的勾股数
  1. Module[
  2.   {found, cnt, i, j, k},
  3.   found = {};
  4.   cnt = Table[0, {1000}];
  5.   For[i = 1, i < 500, i++,
  6.    For[j = 1, j < i, j++,
  7.     If[2 i j + 2 i i > 1000, Break[]];
  8.     For[k = 1, k < 1000, k++,
  9.      If[k (2 i j + 2 i i) > 1000, Break[]];
  10.      If[!
  11.        MemberQ[found,
  12.         Hash[{2 i j  k, k (i i - j j), k (i i + j j)}]],
  13.       cnt[[k (2 i j + 2 i i)]]++;
  14.       found =
  15.        Append[found, Hash[{2 i j  k, k (i i - j j), k (i i + j j)}]]
  16.       ]
  17.      ]
  18.     ]
  19.    ];
  20.   j = 1;
  21.   For[i = 2, i < 1001, i++, If[cnt[[j]] < cnt[[i]], j = i]];
  22.   j
  23.   ] // Timing
复制代码
时间: {0.030996, 840}

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2010-9-26 21:20:31 | 显示全部楼层 来自 河北廊坊
matlab计算的效率要高一些的
  1. clear;clc;close all
  2. tic;
  3. [a,b]=meshgrid(1:500);
  4. c=a.^2+b.^2;
  5. d=sqrt(c);
  6. f=round(d);
  7. e=f==d;
  8. k=find(e);
  9. p=a(e)+b(e)+f(e);
  10. q=accumarray(p,1);
  11. m=find(q==max(q));
  12. ij=find(p==m);
  13. re=[a(k(ij)) b(k(ij)) f(k(ij))];
  14. re=unique(sort(re,2),'rows');
  15. fprintf('%d^2+%d^2=%d^2\n',re');
  16. toc
复制代码
  1. m =

  2.    840

  3. 40^2+399^2=401^2
  4. 56^2+390^2=394^2
  5. 105^2+360^2=375^2
  6. 120^2+350^2=370^2
  7. 140^2+336^2=364^2
  8. 168^2+315^2=357^2
  9. 210^2+280^2=350^2
  10. 240^2+252^2=348^2
  11. Elapsed time is 0.025446 seconds.
复制代码
回复 不支持

使用道具 举报

发表于 2010-9-27 15:17:57 | 显示全部楼层 来自 北京
此题稍加分析即可笔算出来
回复 不支持

使用道具 举报

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

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-26 00:39 , Processed in 0.040283 second(s), 15 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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