http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1140
反哥德巴赫猜想:任一大于11的奇数,都可表示成两个合数之和
定义反哥德巴赫分拆数g(n)表示将大于11的奇数n分解为两个合数之和的方案数。再定义sg(n)=sum({g(i) | i ≤ n}),即所有不大于n的奇数的反哥德巴赫分拆数之和。你的任务就是快速的计算给定n所对应的sg(n)。
看到题目首先就想到打表,打表这个过程是没错,但是,打表后该怎么做了,这题目有点蛋疼,输出的时候
要输出的它前面的数包括他自己的总和,首先朴素的枚举他前面的所有答案,然后加起来,肯定会超时的。
这题可以打奇合数的表,可以打素数的表,可以找规律,每次方法对应不同的算法,我是打奇合数的表
因为每有一个奇合数,这个奇数,就对应了一个方案,因为在此题目中的要满足奇数=奇合数+偶合数,
顺带一提而且这个奇数A,只有A-4之前的奇合数才能满足要求,比如17的前面奇合数有9 15而15不满足,因为
没有一个和15配对的合数,所以只要算A-4之前的奇合数就行
打完奇合数表就完成第一步了,然后就是怎样算出它前面的数的方案数的总和,我这里用了一个数组
bx[i]表示i这个数之前有多少个奇合数,ax[i]是打出的奇合数的表,满足要求的是1,其他为0
#include <stdio.h>
long long ax[1000005]={0};
long long bx[1000005]={0};
int main()
{
long long i,j,k,m,len=0,a;
for(i=2;i<=500000;i++) //奇合数打表
{
for(j=i+i;j<=1000000;j+=i) //确保是合数,直接从4开始
{
if(j%2==1) //确保是奇数
ax[j]=1;
}
}
for(i=9;i<=1000000;i++)
{
if(ax[i])
len++;
bx[i+4]=len; //bx[i]表示i这个数之前有多少个奇合数,那么必定是i-4前的奇合数才满足要求,因为最小的偶合数是4
}
while(scanf("%I64d",&a)!=EOF)
{
long long sum=0; //防溢出
for(i=13;i<=a;i+=2)
sum+=bx[i];
printf("%I64d\n",sum);//必须用I64d输出不能用long long
}
}