/************************************************************************/ /* 注:leoyonn原创,请注明出处 http://hi.baidu.com/leoyonn */ /************************************************************************/ // 《编程之美》2.20 程序理解和时间分析 不用电脑的帮助,回答下面问题(程序原是Java的,我用C写的) // #include
程序说明:
这个题目总共有三问:
1. 这个程序要找的是什么条件的数?
2. 这个数存在么?符合这一条件的最小的数是什么?
3. 在电脑商运行这一程序,你估计多长时间才能输出第一个结果?时间精确到分钟(单核CPU2.0Hz)
-----------------------------------------------------------------------------------
首先解答1,见程序中//注释@1部分,是我添加的,就是解答这个问题。整个for循环中要求的数是:
从rg[0]到rg[j-1]都能整除i,从rg[j+2]到rg[29]都能整除i,唯独rg[j],rg[j+1]无法整除i,就是要找这样的i。
为了解这个问题,首先得找到rg[j]和rg[j+1],在它们的因子里须有其它rg[]元素分解不出的因子。
例如23,29这样的素数就行,但他们旁边的数大都能被其他数的因子“凑乘”出来,比如24=4x6=2x12..,30 = 3x10.. 等等
最终,我找到了唯一一组连续的数16,17。
由于rg中最大的数是31,所以作为2的幂,16可以满足不被其他数的因子凑出来(虽然能2x8,但2是8的因子,不算);
17是素数,显然满足条件。
这样就可以求解 i 了:i = 2 * 3 * 4 * 5 * ... * 15 * 18 * 19 * 20 *...* 30 * 31;
对了嘛?等等,别急。看这里有2,有4, 有8…… 乘起来早凑出来6了。所以,需要将“多余”的公因子约去再乘。
如下两行为约前与约后的比对:
i1 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 18 * 19 * 20 *...* 30 * 31;
i2 = 2 * 3 * 2 * 5 * 1 * 7 * 2 * 3 * 1 * 11 * 1 * 13 * 1 * ....
比如,*6 变成 *1,是因为前面有了 2 * 3; *8 变成了 *2 ,因为前面有了2 * 2,以此类推。
最后得到了要求的i,最小的:2 1235 8166 0200,2万亿多。在注释2处将初始化i = 1改为这个数,验证正确:)
同时这也解答了第二题。第三题的话就按照这个数算clock cycle吧……