2016合双有什么数?
这个问题问得有点晚了,合数的问题在2015年已经被研究了。 我直接给出结论吧(详细过程见论文): 因此只要保证每个合数都有至少两个因数的平方和大于或等于484就可以了。 那么问题就变成了如何寻找这样的两个素数。
一个比较笨的办法是暴力求解所有可能的素数组合,然后判断它们是不是合数,这个做法时间复杂度为O(p^3),其中p是素数的个数。 但是这样做太傻了,因为所有的素数都是对称的!比如3和5,7和11都是素数对;而9和13也是素数对,只不过其中较大的那个数9比较“奇怪”,它不止两次出现。既然已经知道所有的素数是对称的了,那么我们可以挑选一个比较大的素数对尝试,如果它能成为合数的话,那必然是这两个素数的乘积再加上1成了合数。这样就省去了大量不必要的计算。
我的优化方法是在O(p^2)的时间内找出所有素数对的第一个元素是否小于某个给定的值m。如果是的话,则说明这个素数对可以形成合数,并输出它的第二个元素即可。这个过程其实可以在O(logn)的时间内完成,其中logn是小于m的所有素数的个数。所以整体的时间复杂度就变成了O(logk), k是比较小的那个素的个数。 上面讨论的是两个素数的情况,如果是一堆素数呢? 我的方法是先找出其中的两个素数,让它们形成一位数,然后再看看能不能构成合数。如果能就找到下一个两位数,重复上述操作直到所有素数处理完毕。整个过程的时间复杂度为O(nlogn), n是被处理的素数的个数。 这是我用C语言写的代码,测试了上千次,平均时间不超过1毫秒。大家可以看看效果怎么样。 #include int main() { int i, j; for (i = 0; i < 1e6; ++i) { //循环一千次,每次生成一个新的数组 for (j = 0; j < 1000; ++j) { printf("%d%c", rand() % 10000, " \n"[rand() % 10]); } } return 0; } 用我这个方法需要O(n)的内存,比暴力求解所有可能要节省很多空间。而且只要n足够大,那么出现合数的可能性就会大大增加。不过缺点就是比较慢。但是我想应该慢不到哪里去,因为有这么多素数要检测。