素数价值
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;
}