题目:判断给定的数字能否写成4个素数的和。
分析:数论。1.如果N < 8 不成立;2.如果 N >= 8 时,如果N为奇数则令N = 2 + 3 + K,
N为偶数则令N = 2 + 2 + K这样K为偶数且K>=4,这时满足哥德巴赫猜想:
一个偶数可以拆成2个素数和的形式。通过循环拆解K即可。
素数判定可以利用筛法打表,或者直接按照随机判定算法判定。
注意:数组不要越界。
打表法:
#include <iostream>
#include <cstdlib>
#include <cstring>
using namespace std;
int visit[10000001];
int prime[700001];
int main()
{
memset( visit, 0, sizeof(visit) );
int count = 0;
visit[0] = visit[1] = 1;
for ( int i = 2 ; i < 10000000 ; ++ i )
if ( !visit[i] ) {
for ( int j = i<<1 ; j < 10000000 ; j += i )
visit[j] = 1;
prime[count ++] = i;
}
int n;
while ( cin >> n ) {
if ( n < 8 ) cout << "Impossible." << endl;
else if ( n%2 ) {
for ( int i = 0 ; i < count ; ++ i )
if ( !visit[n-5-prime[i]] ) {
cout << "2 3 " << prime[i] << " " << n-5-prime[i] << endl;
break;
}
}else {
for ( int i = 0 ; i < count ; ++ i )
if ( !visit[n-4-prime[i]] ) {
cout << "2 2 " << prime[i] << " " << n-4-prime[i] << endl;
break;
}
}
}
return 0;
}
随机判定算法:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
LL powmod( int a, int x, int n )
{
if ( x == 1 ) return a+0LL;
LL t = powmod( a, x/2, n );
if ( x%2 ) return ((t*t)%n*a)%n;
else return (t*t)%n;
}
int witness( int a, int n )
{
LL u = n-1LL,d,x;
int t = 0;
for ( ; !(u&0x1) ; u >>= 1 ) ++ t;
d = powmod( a, u, n );
while ( t -- > 0 ) {
x = d; d = (d*d)%n;
if ( d == 1 && x != 1 && x != n-1 ) return 1;
}
return (d != 1);
}
int miller( int n, int s = 10 )
{
if ( n == 2 ) return 1;
if ( n == 1 || !(n&1) ) return 0;
for ( int i = 0 ; i < s ; ++ i )
if ( witness( rand()%(n-1)+1, n ) )
return 0;
return 1;
}
int main()
{
int n;
while ( cin >> n ) {
if ( n < 8 ) cout << "Impossible." << endl;
else if ( n <= 9 ) cout << "2 2 2 " << n-6 << endl;
else {
if ( n%2 ) cout << "2 3 ";
else cout << "2 2 ";
n = n-n%2-4;
for ( int i = 3 ; i <= n ; i += 2 )
if ( miller(i) && miller(n-i) ) {
cout << i << " " << n-i << endl;
break;
}
}
}
return 0;
}