我们先来看一个题目:
题目描述
哥德巴赫猜想(Goldbach conjecture):任一大于2的偶数都可写成两个素数之和。 1742年6月,在哥德巴赫写给欧拉(Euler)的信中提出这个问题,目前为止无人证明这一猜想是否正确,最接近的证明结果是中国数学家陈景润在1973年证明的"1+2"成立,即"任一充分大的偶数都可以表示成两个素数的和,或是一个素数与两个素数乘积的和",在超级计算机上验证e3100(≈101346)范围内的偶数均没有找到反例 。
输入
输入一个大于2的偶数N
输出
两个素数a和b,之间有一个空格,并且满足N=a+b且a≤b;
如果N的分解结果不止一组素数,则输出相差绝对值最大的一组
样例输入 Copy
4
10
样例输出 Copy
2 2
3 7
SP:这题的主要思路是:两个素数相加,要等于我们想要的偶数。
代码如下:
#include<stdio.h>
int su(int a);//求出小于等于a的最大素数
int main()
{
int num,i,j,flag=0;
scanf("%d",&num);
for(i=2;i<num;i++)
{
for(j=2;j<num;j++)
{
if(su(i)+su(j)==num)//判断成功则跳出循环
{
printf("%d %d\n",su(i),su(j));
flag=1;
if(flag==1)
{
break;
}
}
}
if(flag==1)
{
break;
}
}
return 0;
}
int su(int a)
{
int i,j,t1=2,t2,flag=1;
for(i=2;i<=a;i++)
{
for(j=2;j<i;j++)
{
if(i%j==0)
{
flag=0;
}
}
if(flag==1)
{
t2=i;
t1=t2;
}
else
{
t2=t1;
}
flag=1;
}
return t2;
}
我们可以看到这个程序的main()函数有4层循环(两个for循环+su()函数里的两个循环),运行效率是非常低下的。
既然这样我们就一步一步优化我们的程序:
#include<stdio.h>
#include<math.h>
int su(int a);//求出小于等于a的最大素数
int main()
{
int num,i,j,flag=0;
scanf("%d",&num);
for(i=2;i<num;i++)
{
j=num-i;//for(j=2;j<num;j++) 优化循环
if(su(i)+su(j)==num)//判断成功则跳出循环
{
printf("%d %d\n",su(i),su(j));
flag=1;
if(flag==1)
{
break;
}
}
}
return 0;
}
int su(int a)
{
int i,j,t1=2,t2,flag=1;
for(i=2;i<=a;i++)
{
for(j=2;j<=(int)sqrt(i);j++)//优化算法
{
if(i%j==0)
{
flag=0;
}
}
if(flag==1)
{
t2=i;
t1=t2;
}
else
{
t2=t1;
}
flag=1;
}
return t2;
}
但是我们仍然发现我们的su()太复杂了,所以我们需要换个思路,su()函数就用来判断素数,是就返回该素数,否就返回0
#include<stdio.h>
#include<math.h>
int su(int a);//判断a是否为素数
int main()
{
int num,i,j,flag=0;
scanf("%d",&num);
for(i=2;i<num;i++)
{
j=num-i;//for(j=2;j<num;j++) 优化循环
if(su(i)+su(j)==num)//判断成功则跳出循环
{
printf("%d %d\n",su(i),su(j));
flag=1;
if(flag==1)
{
break;
}
}
}
return 0;
}
int su(int a)
{
int i;
for(i=2;i<(int)sqrt(a);i++)
{
if(a%i==0)
{
return 0;
}
}
return a;
}
最后程序就只剩两层循环了。
程序优化真是一件不可思议的事,用这个的方法能输入到10^30,之后就有点慢了。但是用最开始的方法到10^6就开始慢了。