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