这是《编程之美》的2.20题目,给出一段C#代码,要求不用电脑,理解程序并回答问题。下面是从C#代码中改写成的C++代码:
#include <iostream>#include <limits>using namespace std;int 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}; for(__int64 i =1; i < numeric_limits<__int64>::max(); i++) { int hit = 0; int hit1 = -1; int hit2 = -1; for(int j = 0; j < sizeof(rg)/sizeof(*rg) && (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) { cout << "find " << i << endl; break; } } return 0;}
理解这个程序就是从输出的地方往前追溯就可以。这个程序输出的条件是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是:23*33*52*7*11*13*19*23*29*31,用计算器计算出这个数是:2123581660200。可以把上述程序中的for循环中的i初始化成这个数来检验。
JOJ的2042题目也是一个程序理解题目,这个题目非常有意思,给出了下面一段C++源代码,要求计算出最后的输出结果,源代码如下:
#include<cstdio>int main(void){ int x = 987654321, c = 0, d = 1, e = 6; while(x--){ c += d, d += e, e += 6; } printf("%d/n", c); return 0;}
原题目如下:
Wecan use axioms to calculate programs just like what we do in algebras. Dijkstrais the one who advocates such constructive approach whereby a program isdesigned together with its correctness proof. In short, one has to start from agiven postcondition Q and then look for a program that establishes Q from theprecondition. Often, analyzing Q provides interesting hints to finding theprogram. This approach is quite different from the well known Hoare Logic.
Forexample, the following program is calculated by Dijkstra's approach.Unfortunately, its annotation is lost so that its function is hard to grasp.You are to help with finding the final value of the variable c. Note that theprogram is designed under 128-bit architecture.
代码就是上面那一段。
这个题目通过小数据计算可以看出规律:x=1,c = 1; x=2, c=8; x=3, c=27; x=4, c=64,于是可以猜测这段程序是用来计算x^3的。用计算器计算出987654321^3,提交上去就AC了。
这个题目是超级大牛SIYEE出的。从题目本身的叙述中就学到了很多东西。又知道了一个数的立方还可以这样计算。可惜数学功底差,不知道在数学上是如何推导出来的。
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow