题目链接:哆啦A梦传送门
题解:
导论:
今日常见的猜想陈述为欧拉的版本,即任一大于2的偶数都可写成两个素数之和,亦称为“强哥德巴赫猜想”或“关于偶数的哥德巴赫猜想”。
从关于偶数的哥德巴赫猜想,可推出:任一大于7的奇数都可写成三个质数之和的猜想。后者称为“弱哥德巴赫猜想”或“关于奇数的哥德巴赫猜想”。
我们证明下:任一大于7的奇数都可写成三个质数之和的猜想。当一个数为奇数时,我们是不是可以将它变为偶数(减去一个奇数),然后去满足欧拉的版本。那么此时最小的奇数(满足三个质数之和)就为2+2+3=7。证毕。
那么我们现在回到这题:
参考链接:
https://blog.csdn.net/ACdreamers/article/details/8575023
https://blog.csdn.net/weixin_43532890/article/details/83582924
当此数位偶数时,那么他的价值自然就是2了。
当一个数为奇数时:判断当前数是否为素数,如果是则价值为1,否则将此数减2(只有2为是偶数中的素数),判断减2后是否为素数,如果是价值为2。(我们也可以不减2,我们减3,那么此时数就变成偶数,价值就变为3了,但我们要价值最小,所以先判断减2的情况)
否则用这个数除以比他小的素数,当可以整除时,判断整除后的数是否为素数,是价值为2,否则价值为3,如果没有可整除的素数,那么这个数的价值为3.
#include
using namespace std;
int tot,prime[50010];
bool vis[50010];
int ans[50010];
void init()
{
int n=50002;
for(int i=2;i<=n;i++)
{
if(!vis[i]){
prime[++tot]=i;
ans[i]=1; ///此数为素数
ans[i+2]=2; ///这就相当于减2的情况
}
for(int j=1;j<=tot&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
for(int i=1;i<=tot;i++)
{
for(int j=1;j<=tot;j++)
{
int t=prime[i]*prime[j];
if(t>n) break;
ans[t]=2; ///这就是整除的情况,说明此数能整除一位素数
}
}
///偶数的价值都为2
for(int i=4;i<=n;i+=2)
ans[i]=2;
///其它大于7的奇数都可写成三个质数之和的猜想
for(int i=2;i<=n;i++){
if(!ans[i]) ans[i]=3;
}
///统计前缀和
for(int i=2;i<=n;i++)
{
ans[i]+=ans[i-1];
}
}
int main()
{
init();
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",ans[b]-ans[a-1]);
}
return 0;
}
做个有情怀的程序员。