楼主: tree_new_bee

Euler Project 挨个做- 之二 (Q51-Q78)

[复制链接]
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
191#
 楼主| 发表于 2012-2-10 23:50 | 只看该作者
重写出上面的Q31后, 下面的Q77应该就容易做了。

Q77. What is the first value which can be written as the sum of primes in over five thousand different ways?

t is possible to write ten as the sum of primes in exactly five different ways:

7 + 3
5 + 5
5 + 3 + 2
3 + 3 + 2 + 2
2 + 2 + 2 + 2 + 2

What is the first value which can be written as the sum of primes in over five thousand different ways?

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
192#
发表于 2012-2-11 00:13 | 只看该作者
tree_new_bee 发表于 2012-2-8 16:18
Q76 It is possible to write five as a sum in exactly six different ways:

4 + 1

Q76似乎用抽屉原理+排列组合就可以搞定

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
193#
发表于 2012-2-11 00:18 | 只看该作者
tree_new_bee 发表于 2012-2-10 23:50
重写出上面的Q31后, 下面的Q77应该就容易做了。

Q77. What is the first value which can be written a ...

Q77我猜一下,这个数不超过799

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
194#
发表于 2012-2-11 03:57 | 只看该作者
tree_new_bee 发表于 2012-2-10 23:50
重写出上面的Q31后, 下面的Q77应该就容易做了。

Q77. What is the first value which can be written a ...

对,把COINS表换成素数表就行。

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
195#
 楼主| 发表于 2012-2-11 21:12 | 只看该作者
newkid 发表于 2012-2-11 03:57
对,把COINS表换成素数表就行。

也不是想象的那么简单,转的时候还是费了不少脑筋。
  1. create or replace procedure Q77(arg number default 100) is
  2. type t_nlist is table of number index by pls_integer;
  3. type t_nlistlist is table of t_nlist index by pls_integer;

  4. nlist t_nlistlist;
  5. primlist t_numlist;
  6. coins t_numlist := new t_numlist();
  7. sm number;
  8. begin

  9. primlist := pkg_prim2.seive_numlist(arg);
  10. coins.extend(primlist.count+1);
  11. coins(1) := 1;
  12. for i in 1..primlist.count loop
  13.   coins(i+1) := primlist(i);
  14. end loop;

  15. for i in 1..arg loop
  16.     nlist(1)(i) := 0;
  17.     nlist(i)(1) := 0;
  18. end loop;
  19.   
  20. for i in 2..arg loop
  21.   for j in 2..coins.count loop
  22.       if coins(j)<i then
  23.         nlist(i)(coins(j)) := nlist(i-coins(j))(coins(j)) + nlist(i)(coins(j-1));
  24.       elsif coins(j)=i then
  25.         nlist(i)(coins(j)) := nlist(i)(coins(j-1)) + 1;
  26.       elsif coins(j)>i then
  27.         nlist(i)(coins(j)) :=nlist(i)(coins(j-1));
  28.       end if;
  29.       
  30.   end loop;

  31.   for j in 2..arg loop
  32.     if not nlist(i).exists(j) then
  33.       nlist(i)(j) := nlist(i)(j-1);
  34.     end if;
  35.   end loop;
  36.   --dbms_output.put_line('i=' || i || ', p(i)=' || nlist(i)(i));
  37.   if nlist(i)(i) > 5000 then
  38.      dbms_output.put_line('result=' || i || ', p(i)=' || nlist(i)(i));
  39.      return;
  40.   end if;
  41. end loop;

  42. dbms_output.put_line('no result! try big arg.');
  43. end Q77;
复制代码
SQL> exec q77(100)

result=71, p(i)=5007

PL/SQL procedure successfully completed

Executed in 0.094 seconds

SQL>

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
196#
 楼主| 发表于 2012-2-11 21:40 | 只看该作者
Q78. Find the least value of n for which p(n) is divisible by one million.

Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can separated into piles in exactly seven different ways, so p(5)=7.
OOOOO
OOOO   O
OOO   OO
OOO   O   O
OO   OO   O
OO   O   O   O
O   O   O   O   O

Find the least value of n for which p(n) is divisible by one million.


看上去与前两题相似, 但因为要算的数很大,有可能要用大数运算。 并且性能也许有问题。

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
197#
 楼主| 发表于 2012-2-11 21:43 | 只看该作者
本帖最后由 tree_new_bee 于 2012-2-11 21:52 编辑

基本照抄过来Q76的代码,试了试:
  1. create or replace procedure Q78(arg number default 100) is
  2. type t_nlist is table of number index by pls_integer;
  3. type t_nlistlist is table of t_nlist index by pls_integer;

  4. nlist t_nlistlist;
  5. sm number;
  6. begin
  7. for i in 1..arg loop
  8.     nlist(1)(i) := 1;
  9.     nlist(i)(1) := 1;
  10. end loop;
  11.   
  12. for i in 2..arg loop
  13.   for j in 2..arg loop
  14.       if j<i then
  15.         nlist(i)(j) := nlist(i-j)(j) + nlist(i)(j-1);
  16.       elsif j=i then
  17.         nlist(i)(j) := nlist(i)(j-1) + 1;
  18.       elsif j>i then
  19.         nlist(i)(j) :=nlist(i)(j-1);
  20.       end if;
  21.   end loop;
  22. if nlist(i)(i)mod 1e6 = 0 then
  23.      dbms_output.put_line('result=' || i || ', p(i)=' || nlist(i)(i));
  24.      return;
  25.   end if;
  26. end loop;
  27. dbms_output.put_line('no result! try big arg.');
  28. end Q78;
复制代码
参数试到2000时,出来了结果:

SQL> exec q78(2000)

result=1759, p(i)=4280750559177948266124532321685590709000000

PL/SQL procedure successfully completed

Executed in 1.232 seconds



但是, 别急。 填进去这个答案,是错的。
为什么呢? 看看得到的 p(i)=4280750559177948266124532321685590709000000, 6个0前面的位数是38位, 正好是oracle number的精度。
所以这个数能被1000000整除是假的。

并且, 先不说大数问题(有大数包, 大数不是问题),  注意参数为2000已经要1秒多了(在100-200时,速度0.0x秒), 如果结果是上万的, 那么也许就很难出来了。

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
198#
 楼主| 发表于 2012-2-11 21:48 | 只看该作者
lastwinner 发表于 2012-2-11 00:18
Q77我猜一下,这个数不超过799


对了, 但超出的太多。
不知怎么猜的?

在结果没出来之前, 试着猜猜Q78的答案范围?

使用道具 举报

回复
论坛徽章:
10
CTO参与奖
日期:2009-02-20 09:44:20ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30迷宫蛋
日期:2012-05-07 10:55:58茶鸡蛋
日期:2012-04-19 16:08:262012新春纪念徽章
日期:2012-01-04 11:54:462011新春纪念徽章
日期:2011-01-04 10:24:02数据库板块每日发贴之星
日期:2010-12-19 01:01:02数据库板块每日发贴之星
日期:2010-12-13 01:01:012009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2014-02-08 06:00:12
199#
 楼主| 发表于 2012-2-11 22:05 | 只看该作者
改成大数运算, 性能骤降许多!
  1. create or replace procedure Q78(arg number default 100) is
  2. type t_nlist is table of varchar2(1000) index by pls_integer;
  3. type t_nlistlist is table of t_nlist index by pls_integer;

  4. nlist t_nlistlist;
  5. begin
  6. for i in 1..arg loop
  7.     nlist(1)(i) := '1';
  8.     nlist(i)(1) := '1';
  9. end loop;
  10.   
  11. for i in 2..arg loop
  12.   for j in 2..arg loop
  13.       if j<i then
  14.         nlist(i)(j) := pkg_bignum.bigplus(nlist(i-j)(j) , nlist(i)(j-1));
  15.       elsif j=i then
  16.         nlist(i)(j) := pkg_bignum.bigplus(nlist(i)(j-1) , 1);
  17.       elsif j>i then
  18.         nlist(i)(j) :=nlist(i)(j-1);
  19.       end if;
  20.   end loop;
  21. if substr(nlist(i)(i), -6) = '000000' then
  22.      dbms_output.put_line('result=' || i || ', p(i)=' || nlist(i)(i));
  23.      return;
  24.   end if;
  25. end loop;
  26. dbms_output.put_line('no result! try big arg.');
  27. end Q78;
复制代码
SQL> exec q78(1000)

no result! try big arg.

PL/SQL procedure successfully completed

Executed in 1.467 seconds

SQL> exec q78(2000)

no result! try big arg.

PL/SQL procedure successfully completed

Executed in 82.774 seconds

SQL>


2000比1000慢许多, 是因为在大数包中,对于小与1e35的数是直接用数学计算去算的,到了1000以后, 大部分的计算都真正采用字符进行大数运算, 要慢的多。

看来这个算法的路走到尽头了, 要重新寻找新的思路。

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
200#
发表于 2012-2-11 22:28 | 只看该作者
tree_new_bee 发表于 2012-2-11 21:48
对了, 但超出的太多。
不知怎么猜的?

10有5种不同的素数和的写法,而且对于一个偶数,最长的写法总是一串2的和
如果满足条件的数是1000,那么最长的写法就是500个2,而加数最少可以是两个质数
加数个数从2到500,变化太多了,保守算也至少有(500-2+1)/2=254种那么多……(猜的时候就想到这么多,然后一想,若为1000,太多了,减少到800也肯定能让结果超过5000,于是就猜了个799)

————————————以下是回应你的问题时写的—————————————————
如果满足条件的数是1000,那么最长的写法就是500个2,而3个2可以拆为两个3,因此2和3的组合写法,可以有大约(500-2)/3=166那么多种,不去细算,1000以内的素数至少有100个,而任意一个质数,都可以表示为一个或两个2与若干3的和(用这个方式可以保证构造出的加数组合不重复)
5=2+3,于是166种2和3的组合,可以转化为166种一个5与2和3的组合
7=2+2+3,于是166种2和3的组合,可以转化为165种一个7与2和3的组合
……
如此下去,到第100个质数的时候,只替换出一个非2和3的质数,可能的质数组合将达到10000左右,远远超出了5000
昨天如果想到这么远,那么我连799都不会猜了。本来想赌300的,不过没细算就没猜,呵呵

使用道具 举报

回复

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

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表