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

这是《编程之美》的2.20题目,给出一段C#代码,要求不用电脑,理解程序并回答问题。下面是从C#代码中改写成的C++代码:

[cpp] 
view plain
copy

  1. #include <iostream>  
  2. #include <limits>  
  3. using namespace std;  
  4. int main() {  
  5.      int rg[] = {2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,  
  6.          20,21,22,23,24,25,26,27,28,29,30,31};  
  7.      for(__int64 i =2123581660200; i < numeric_limits<__int64>::max(); i++) {  
  8.          int hit = 0;  
  9.          int hit1 = -1;  
  10.          int hit2 = -1;  
  11.          for(int j = 0; j < sizeof(rg)/sizeof(*rg) && (hit <= 2); j++) {  
  12.               if((i % rg[j]) != 0) {  
  13.                    hit++;  
  14.                    if(hit == 1) {  
  15.                        hit1 = j;  
  16.                    } else if(hit == 2) {  
  17.                        hit2 = j;  
  18.                    } else break;  
  19.               }  
  20.          }  
  21.          if((hit == 2) && (hit1+1==hit2)) {  
  22.               cout << “find “ << i << endl;  
  23.               break;  
  24.          }  
  25.      }  
  26.      return 0;  
  27. }  

理解这个程序就是从输出的地方往前追溯就可以。这个程序输出的条件是hit==2&&(hit1+1==hit2),再往前追溯看hit,hit1,hit2三个变量分别代表什么,hit表示满足i%r[j]!=0的条件的次数,hit==2表示这个条件只能被满足两次,也就是说对于一个i,在rg数组的30个数中,这个i能被其它28个数整除,而不能被其中两个数整除。而hit1表示第一个不能整除i的数的下标,hit2表示第二个不能整除i的下标,这两个下标被要求相差只有1。于是,程序所要寻找的是这样的数:这个数i不能被2-31这30个数中的两个相邻的数整除,但能被其它28个数整除。所以,这个i肯定是其它28个数的最小公倍数的整数倍。然而i不能被两个相邻的数整除,所以必然是分解质因子后要么i的质因子中不包括这两个数的质因子,要么是i的质因子的次数小于这两个数中相同质因子的次数。

那么,只需要给2-31这30个数分解质因数,找一下是否有这样的相邻的两个数,要么它们的质因子中有其它数没有的质因子,要么对于相同的一个质因子,这两个数包含这个质因子的次数高于其它所有次数。

16、17、19、23、25、27、29、31这几个数包含次数最高的质因子。而相邻的则只有16,17。所以,这段程序所要求的数i就是,它不能被16、17整除,但能被30个数中的其它28个数整除,最小的i就是其它28个数的最小公倍数,从上表中知道,这个最小的i是:2
3
*3
3
*5
2
*7*11*13*19*23*29*31,用计算器计算出这个数是:2123581660200。可以把上述程序中的for循环中的i初始化成这个数来检验。


参考:http://blog.csdn.net/jcwKyl/article/details/3889802

    原文作者:CourageK
    原文地址: https://blog.csdn.net/u011487593/article/details/48372669
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞