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

素数价值

Time Limit:3000ms

Memory Limit:65536K

Description

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

Input

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

Output

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

Sample Input

2
2 3
2 5

Sample Output

2
5

思路

思路

根据哥德巴赫猜想可知:即任一大于2的偶数都可写成两个素数之和,任一大于7的奇数都可写成三个质数之和。

所以一个大于等于2的数的素数价值最大为3,最小为1.

当一个数为偶数时:这个数且不等于2,他的价值为2

当一个数为奇数时:判断当前数是否为素数,如果是则价值为1,否则将此数减2(只有2为是偶数中的素数),判断减2后是否为素数,如果是价值为2,否则用这个数除以比他小的素数,当可以整除时,判断整除后的数是否为素数,是价值为2,否则价值为3,如果没有可整除的素数,那么这个数的价值为3.

#include<iostream>

using namespace std;

#define MAXN 50005

int prime[MAXN];
int value[MAXN];
void get_prime() //求素数,利用素数打表法
{
    for(int i=2;i<MAXN;i++)
    {
        if(!prime[i])
        {
            for(int j=2;j*i<=MAXN;j++)
            {
                prime[i*j]=1;//not prime
            }
        }
    }
}

void get_value()
{
    int prime_value = 0;
    for(int i=2;i<=50000;i++)
    {
        if(i%2==0 && i!=2)//大于2的偶数的价值为2
        {
            prime_value+=2;
        }
        else 
        {
            if(!prime[i])//本身为素数,价值为1
            {
                prime_value++;
            }
            else
            {
                if(!prime[i-2])//减去2,为素数价值为1
                {
                    prime_value+=2;
                }
                else 
                {
                    bool is_add = true;
                    for(int j=3;j<i;j+=2)//整除素数
                    {
                        if(i%j==0)
                        {
                            if(!prime[i/j])//整除后是素数,价值为2
                                prime_value+=2;
                            else 
                                prime_value+=3;//否则为2
                            is_add = false;
                            break;
                        }
                    }
                    if (is_add)//不能整除所有素数,这个数的价值为3
                        prime_value+=3;
                }        
                
            }
        }
        value[i] = prime_value;//记录前i个数的素数价值
    }
}

int main()
{
    get_prime();//打表
    get_value();//计算
    int t;
    cin>>t;
    while(t--)
    {
        int a,b;
        cin>>a>>b;
        cout<<value[b] - value[a-1]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43532890/article/details/83582924