nefu 394 素数价值(dp或规律)
素数价值 |
||
|
||
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
|
||
hint |
||
|
|
||
source
哥德巴赫猜想:任何大于偶数都等于两个素数和; 分类:1大于2的偶数,价值为2 2:奇数:若是质数价值为1,若是等于两个质数之积价值是2,若是等于2加上某个质数价值等于2,其他价值等于3
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 50003
using namespace std;
bool noprime[N];
int prime[N];
int num;
int f[N];
void pprim()
{
memset(noprime,0,sizeof(noprime));
noprime[0]=1;noprime[1]=1;
num=0;
memset(f,0,sizeof(f));
f[2]=1;
for(int i=2;i<N-2;i++)
{
if(!noprime[i])
{
prime[num++]=i;
f[i]=1;//质数
f[i+2]=2;//质数+2
for(int j=i+i;j<N;j+=i)
{
noprime[j]=1;
}
}
}
int z;
for(int i=0;i<num;i++)
for(int j=0;j<num;j++)
{
z=prime[i]*prime[j];
if(z<N)
f[z]=2;
else break;
}
for(int i=4;i<N;i+=2)//偶数
f[i]=2;
for(int i=3;i<N;i+=2)//其他类
if(f[i]==0)f[i]=3;
}
int main()
{
int a,b;
pprim();
int cas;
scanf("%d",&cas);
//while(scanf("%d",&cas)!=EOF)
// {
// freopen("1.txt","w",stdout);
while(cas--)
{
scanf("%d%d",&a,&b);
int sum=0;
for(int i=a;i<=b;i++)
sum+=f[i];
//for(int i=2;i<N;i++)
//printf("%d %d\n",i,f[i]);
printf("%d\n",sum);
}
// }
}
先预处理DP #include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int MAXP = 50100;
const int N = 50000;
int prime[MAXP] = {0},num_prime = 0;
int isNotPrime[MAXP] = {1, 1};
void prime_select()
{
int i;
for(int i = 2 ; i < MAXP ; i ++)
{
if(! isNotPrime[i])
prime[num_prime ++]=i;
for(int j = 0 ; j < num_prime && i * prime[j] < MAXP ; j ++)
{
isNotPrime[i * prime[j]] = 1;
if( !(i % prime[j]))
break;
}
}
}
int dp[MAXP];
inline int minx(const int &a, const int &b)
{
return a > b ? b : a;
}
void doDp()
{
memset(dp, -1, sizeof(dp));
int i, j, k;
dp[0] = 0;
for (i = 0; i <= N; i ++)
{
if(i == 1)
continue;
for (j = 0; j < num_prime && i + prime[j] <= N; j ++)
{
if(dp[i + prime[j]] == -1)
dp[i + prime[j]] = dp[i] + 1;
dp[i + prime[j]] = minx(dp[i + prime[j]], dp[i] + 1);
}
if(i != 0)
for (j = 0; j < num_prime && i * prime[j] <= N; j ++)
{
//isPrime
if(dp[i * prime[j]] == -1)
dp[i * prime[j]] = dp[i] + 1;
dp[i * prime[j]] = minx(dp[i * prime[j]], dp[i] + 1);
}
}
return ;
}
int main()
{
//freopen("2.out","w",stdout);
prime_select();
doDp();
int n, a, b;
int i;
int t;
scanf("%d", &t);
while (t --)
{
scanf("%d %d", &a, &b) ;
int ans = 0;
//for(int i=2;i<N;i++)
//printf("%d %d\n",i,dp[i]);
for (i = a; i <= b; i++)
ans += dp[i];
printf("%d\n", ans);
}
return 0;
}
|
The article write by nealgavin

浙公网安备 33010602011771号