现在的位置: 首页 > 综合 > 正文

nefu 394 素数价值(dp或规律)

2013年12月09日 ⁄ 综合 ⁄ 共 2338字 ⁄ 字号 评论关闭

素数价值

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

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
dp[i + prime[j]] = minx(dp[i + prime[j]], dp[i] + 1);

dp[i * prime[j]] = minx(dp[i * prime[j]], dp[i] + 1);
然后统计.

#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;

}

 

 

 

 

 

 

 

 

 

抱歉!评论已关闭.