素数价值【技巧:哥德巴赫猜想】

内容:

我们来定义下一个数的素数价值,假设这个数是N(2<=N<=50000),我们可以通过以下两种方法:
1.把当前数字除以某个素数(当然得可以整除),即N = N / p;
2.把当前数字减去某个素数(保证减后结果为正整数),即N = N - p;
这个数字的素数价值是最少得通过多少次以上的方法使得它变成0.

第一行是测试数据的组数T,接着有T组测试数据.每组测试数据有两个数字a,b(2<=a<=b<=50000).

对于每组测试数据,输出区间[a,b]之间所有数字的素数价值的和.

思路:

利用哥德巴赫猜想:偶数=2素数和;

但是,当为奇数时:需要考虑第一种情况,将50000以内素数打表(打表只需到sqrt(50000)即可),看当前值是否能整除开一个素数;

当整除开一个素数后又分俩情况:当除得结果:(1)也为素数;(2)不为素数;

最后把所有算的数的和都预处理到一个数组中即:table[i]:1~i的价值和,最后直接求table[b]-table[a-1]即可

代码:

#include <iostream>
#include <cstdio>
#include <math.h>
using namespace std;
bool judge(int n){//判断素数
    if(n<=1) return false;
    if(n == 2 || n == 3) return true;
    if(n % 6 != 1 && n % 6 != 5) return false;
    for(int i=5;i<sqrt(n)+1;i+=6) if(n % i == 0 || n % (i+2) == 0) return false;
return true;}
int table[50005],prime[500],num;
void pretreatment(){//将srqt(50000)素数找到
    for(int i=2;i<=sqrt(50000);i++) if(judge(i)) prime[num++] = i;
}
void fun(){
    int cot = 0;
    for(int i=2;i<=50000;i++)
    {
        if(judge(i)) cot++;//本身为素数
        else
        {
            if(i % 2 == 0) cot += 2;//偶数=2个素数:哥德巴赫猜想
            else
            {
                int temp = i;
                if(judge(temp-2)) cot+=2;//当奇数时,减去一个素数后,另一个已素数
                else
                {
                    int j;for(j=0;j<num;j++)//可能出现除以一个素数
                    {
                        if(temp % prime[j] == 0)
                        {
                            int tt = temp/prime[j];
                            if(judge(tt)) cot+=2;//除以一个素数后另一个也为素数
                            else cot += 3;//另一个不为素数
                            break;
                        }
                    }
                    if(j == cot) cot += 3;//不能整除素数的,只能化为一个偶数+一个素数
                }
            }
        }
        table[i] = cot;//将每个位置预处理成1~i的所有价值和
    }
return;}
int main()
{
    int t,a,b;
    pretreatment();fun();
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&a,&b);
        printf("%d\n",table[b]-table[a-1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值