《编程之美》2.20 程序理解和时间分析

/************************************************************************/ /* 注:leoyonn原创,请注明出处 http://hi.baidu.com/leoyonn */ /************************************************************************/ // 《编程之美》2.20 程序理解和时间分析 不用电脑的帮助,回答下面问题(程序原是Java的,我用C写的) // #include #include void main() { int rg[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; //注释@1 __int64 xx = 8 * 27 * 25 * 7; xx *= 11 * 13 * 19; xx *= 23 * 29 * 31; printf("%I64d", xx); //注释@2 int rgSize = sizeof(rg) / sizeof(int); __int64 MAX64 = (unsigned __int64 (-1)) >> 1; for(__int64 i = xx - 1; i < MAX64; i ++) { int hit = 0, hit1 = -1, hit2 = -1; for(int j = 0; (j < rgSize) && (hit <= 2); j ++) { if((i % rg[j]) != 0) { hit ++; if(hit == 1) { hit1 = j; } else if(hit == 2) { hit2 = j; } else break; } } if((hit == 2) && (hit1 + 1 == hit2)) { printf("found %I64d", i); break; } } }

程序说明:

这个题目总共有三问:
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吧……

你可能感兴趣的:(《编程之美》2.20 程序理解和时间分析)