思路:对偶数4,只有一种分解,即:4 = 2 + 2。
对任何一个不小于6的偶数n,假设它可以表示两个数之和:n = a + b,如果a和b都是素数,则这是一种满足要求的分解形式。枚举所有可能的(a, b)组合,判断是否满足题目的要求。为了减少枚举的次数,本题可以采取如下的策略:
(1) 最小的素数是2,但在本题中,从a = 3开始枚举,因为如果a的值为2,则b的值为大于2的偶数,不可能是素数;
(2) 在枚举过程中,a的值每次递增2,而不是1。这是因为如果每次递增1,在枚举过程中a的值可以取到偶数,而每次递增2,则可以跳过偶数,减少很多次枚举。
(3) 另外,a的值只需枚举到n/2即可,因为如果继续枚举,则枚举得到的符合要求的分解形式只不过是交换了a和b的值而已。
完整代码:
#include<stdio.h>
#include<math.h>
int prime(int n)
{
int i = 0;
for(i=2;i<=sqrt(n);i++)
{
if(n % i == 0)break;
}
if(i>sqrt(n))
{
return 0;
}
return 1;
}
int main()
{
int n = 0;
int i = 0;
while(1)
{
scanf("%d",&n);//容易丢掉取地址符&
if(n==0)break;
if(n==4)
{
printf("4 = 2 + 2\n");
continue;
}
for(i=3;i<=n/2;i+=2)//从i=3开始枚举,每次递增2,跳过偶数
{
if(!prime(i))
{
int j = 0;
j = n - i;
if(!prime(j))printf("%d = %d + %d\n",n,i,j);
}
}
}
return 0;
}
完整代码:
#include <stdio.h>
#include <math.h>
int prime( int m ) //判断m是否为素数,如果为素数,返回1,否则返回0。
{
int i, k = sqrt(m);
for( i=2; i<=k; i++ )
if( m%i==0 ) break; //如果i能整除m,提前退出循环
if (i>k) return 1; //m为素数
else return 0; //m为合数
}
int main( )
{
int m, a, b, count;
while( 1 ) {
scanf( "%d", &m ); //输入一个整数
if( !m ) break;
if( m==4 ) { printf( "1\n" ); continue; }
count = 0; //满足条件的素数对个数
for( a=3; a<=m/2; a=a+2 ) { //从a=3开始枚举,每次递增2,跳过偶数
if( prime(a) ) { //如果a为素数,再判断b是否为素数
b = m - a; if( prime(b) ) count++;
}
}
printf( "%d\n", count );
}
return 0;
}
可能的问题:运行超时。因为m取值可以取到32768,测试数据较多。
改进措施:采用筛选法找出范围内的所有素数。
完整代码:
#include<stdio.h>
#include<math.h>
//pow函数的返回类型是double,取整数需要强制类型转换
//int main()
//{
// printf("%d\n",(int)pow(2,15));//32768
// int i = 0;
// int j = 0;
// int count = 0;
// int temp = 0;
// for(i=2;i<=32768;i++)
// {
// temp = 0;
// for(j=2;j<=sqrt(i);j++)
// {
// if(i % j == 0)temp = 1;
// }
// if(temp == 0)count++;
// }
// printf("%d\n",count);//3512
// return 0;
//}
#define MAX 32768
int prime[3512];
int count[MAX+1];
int arr[MAX+1];//为了能够使用 1 到 MAX 的索引
int main()
{
int i,j,p,k;
for(i=0;i<=MAX;i++)arr[i] = i;
for(i=2;i<=MAX;i++)
{
if(arr[i])p = arr[i];
for(k=p*2;k<=MAX;k+=p)
{
arr[k] = 0;
}
}
for(i=2,j=0;i<=MAX;i++)
{
if(arr[i]!=0)
{
prime[j] = arr[i];
j++;
}
}
//枚举所有不同的素数对(prime[i], prime[k]),如果其和sum不超过MAX,则count[sum]自增1
int sum = 0;
for(i=0;i<j;i++)
{
for(k=i;k<j;k++)
{
sum = prime[i] + prime[k];
if(sum<=MAX)count[sum]++;
}
}
int m = 0;
while(scanf("%d",&m) && m)
{
printf("%d\n",count[m]);
}
return 0;
}