题目大意:每个数字都可以表示为一些素数的和,原因很显然:由算数基本定理可知,每一个数都可以表示为素数的乘积,自然也就可以表示为一些素数的和咯。
于是题目让我们求在这样的表示中出现的最大的素数是第几个素数。
思路:一开始想都没想,上了一个这样的代码。
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 1000000; 7 const int M = 100000; 8 bool is_prime[N]; 9 int prime[M]; 10 int cnt; 11 12 void sieve() 13 { 14 memset( is_prime, 1, sizeof(is_prime) ); 15 is_prime[0] = is_prime[1] = 0; 16 for ( int i = 2; i < N; i++ ) 17 { 18 if ( is_prime[i] ) 19 { 20 int j = i * i; 21 if ( j >= N ) break; 22 while ( j < N ) 23 { 24 is_prime[j] = 0; 25 j += i; 26 } 27 } 28 } 29 cnt = 0; 30 for ( int i = 0; i < N; i++ ) 31 { 32 if ( is_prime[i] ) 33 { 34 prime[cnt++] = i; 35 } 36 } 37 } 38 39 int solve( int n ) 40 { 41 if ( n == 1 ) return 0; 42 int i = 0; 43 while ( prime[i] * prime[i] <= n ) 44 { 45 while ( n % prime[i] == 0 ) 46 { 47 n = n / prime[i]; 48 } 49 i++; 50 } 51 if ( n == 1 ) return i; 52 int pos = lower_bound( prime, prime + cnt, n ) - prime; 53 return pos + 1; 54 } 55 56 int main() 57 { 58 sieve(); 59 int n; 60 while ( scanf("%d", &n) != EOF ) 61 { 62 printf("%d ", solve(n)); 63 } 64 return 0; 65 }
这个代码是可以过的,不过相对比较慢。
其实仔细一想,这样写更好。
1 #include <cstring> 2 #include <cstdio> 3 using namespace std; 4 5 const int N = 1000000; 6 int prime[N]; 7 8 void sieve() 9 { 10 int cnt = 0; 11 memset( prime, -1, sizeof(prime) ); 12 prime[0] = prime[1] = cnt++; 13 for ( int i = 2; i < N; i++ ) 14 { 15 if ( prime[i] == -1 ) 16 { 17 prime[i] = cnt++; 18 for ( int j = i << 1; j < N; j += i ) 19 { 20 prime[j] = prime[i]; 21 } 22 } 23 } 24 } 25 26 int main() 27 { 28 sieve(); 29 int n; 30 while ( scanf("%d", &n) != EOF ) 31 { 32 printf("%d ", prime[n]); 33 } 34 return 0; 35 }
无论是空间时间还是代码总量都要优于第一个方法。