哥德巴赫猜想

思路:对偶数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;
}
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值