2.20 程序理解和时间分析

C++代码如下:

#include <iostream>
#include <vector>
#include <stdint.h>

using namespace std;

int main(void)
{
	vector<int> rg;

	for (int i = 2; i < 32; ++i)
	{
		rg.push_back(i);
	}

	int hit = 0, hit1 = -1, hit2 = -1;

	for (__int64 i = 1; i < INT64_MAX; ++i)
	{
		for (unsigned int j = 0; (hit <= 2) && (j < rg.size()); ++j)
		{
			if (i % rg[j] != 0)
			{
				hit++;
				if (hit == 1)
				{
					hit1 = j;
				}// if
				else if (hit == 2)
				{
					hit2 = j;
				}//else if
				else
				{
					break;
				}// else
			}//end if
		}// end for

		// ! <span style="color:#ff0000;">注意这里if语句的位置</span>
		if (hit == 2 && hit1 + 1 == hit2)
		{
			cout << i << endl;
		}//end if
	}// end for

	return 0;
}


提出三个问题:

问题1:

 这个程序要找的是符合什么条件的数?

问题2:

这样的数存在么?符合这一条件的最小的数是什么?
问题3: 

 在电脑上运行这一程序,你估计要多长时间才能输出第一个结果?时间精确到分钟(电脑配置:单核CPU2.0GHz,内存和硬盘资源充足)


---------------------------分割线 个人一些想法----------------------------

针对问题1:

注意一下if语句的位置,刚开始看题时以为if语句在内层for循环里面,结果就理解错了,错了,了~

仔细分析一下,程序的目的是找出一个数,这个数满足以下性质:

不能被rg数组内的某两个连续数整除,但是能被数组内的其他数整除。

[假设rg数组的元素个数为N 这里 N = 30]


即等价为:<=>

找一个NUM     满足 NUM % rg[i] == 0 && NUM % rg[i + 1] == 0 && NUM % rg[j] != 0 【0≤i<N-1  0≤j<N】


针对问题2:

碰到这种取余的运算,条件反射想到 最小公倍数 最大公约数等等。

恩 但这道题没有那么容易。


首先NUM仅且只能不被两个rg数组内的数整除。 (rg数组内数的范围是2~31)

假设不能被整除的第一个数为rg[i] 第二个即为rg[i + 1]


很显然 15是一个分界线  比如 30 = 2 * 15 那么rg[i] ≤ 15 很明显不行 至少不能被三个数整除。。(想想看 是不是这样)


接下来考虑的就是数组内元素之间的因子转换了  【记得找 大于15的数】

16 = 2 * 8

18 = 2 * 9

20  = 4 * 5

21 = 3 * 7

22 = 2 * 11

24 = 3 * 8

...

30 = 2 * 15


分析一下:

上面列出的一些因子乘式中  两个因子看似没有很大关系 似乎找不到要找的数。

如果NUM能整除两个因子 那么必然NUM肯定能整除它们的乘积(再次想想看 是不是这样)

因此 这样好像就是找不到了。。找不到。。找不到?!


-------------到底错在哪----------------

好吧 其实我们没有考虑两个因子之间的关系 什么关系呢~

----------万一两个因子之间是可以整除的!!!---------

上面满足这一条件的是 16 = 2 * 8   其中因子2可以整除因子8。  


因此  rg[i] = 16  rg[i + 1] = 17


问题转化为 : 找不能被16和17整除 但能被其他数整数整除的数。


接下来找最小的那个。。


任何一个非素数都可以写成 2^k1 * 3^k2 * 5^k3的形式。(k1 k2 k3 ≥ 0)


要想整除16和17外所有的数  这个数至少满足:

整除8 

整除27

整除25

整除其余的素数(除 2 3 5 17外)


即:

2^3 * 3^3 * 5^2 * 7 * 11 * 13 * 19 * 23 * 29 * 31 ===>2123581660200


针对问题3:

参考网络上答案的解释~感谢

【编程之美】2.20程序理解和时间分析 -- 匡子语




再次感叹

数学之美~

编程之美~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值