直接一个个去试
bool is_prime( int m )
{
for ( int i = 2; i < m; ++i ) {
if ( m % i == 0)
return false;
}
return true;
}
可以排除所有除2以外的偶数, 对剩下的奇数进行判断。
bool is_prime( int m )
{
if ( m == 1)
return false;
if ( m == 2)
return true;
if ( m % 2 == 0 )
return false;
for ( int i = 3; i < m; i += 2 )
if ( m % i == 0)
return false;
return true;
}
素数肯定是成对出现的,因此我们可以判断到sqrt(m)
。
bool is_prime( int m )
{
if ( m == 1)
return false;
if ( m == 2)
return true;
if ( m % 2 == 0 )
return false;
for ( int i = 3; i <= m / i; i += 2 )
if ( m % i == 0)
return false;
return true;
}
对于普通筛法我们需要判断sqrt( m ) - 1
个数,然而我们可以通过记录 1 ~ sqrt(m)
内的质数的方式来减少不必要的合数判断。
∀ 合数 a , 必有质因数 p ≤ a 证明 : 设 b 为 a 在 a 以内的因子; 若 b 是素数,则推论成立; 若 b 为合数,根据算数基本定理, b 必有素因子,则 b 的质因数也为 a 的质因数 ; 推论一成立 \forall 合数a, 必有质因数p \le \sqrt{a}\\ 证明: 设b为a在\sqrt{a}以内的因子;\\若b是素数,则推论成立;\\若b为合数,根据算数基本定理,b必有素因子,则b的质因数也为a的质因数;\\ 推论一成立 ∀合数a,必有质因数p≤a证明:设b为a在a以内的因子;若b是素数,则推论成立;若b为合数,根据算数基本定理,b必有素因子,则b的质因数也为a的质因数;推论一成立
也就是说通过求出1 ~ 10
的质数,我们可以筛去11 ~ 100
中的合数,进而剩下的都是质数,
再将其添加到质数表中。
int prime_cnt = 0;
int not_prime[10000 + 1] = {0};
int prime_table[1000] = {};
void era_prime( int maxNum ) {
for ( int i = 2; i <= maxNum; ++i ) {
if ( !not_prime[i]) {
for ( int j = i * i; j <= maxNum; j += i) {
not_prime[j] = 1;
}
prime_table[ prime_cnt++] = i;
}
}
}
∀ a > 1 , a = p 1 r 1 p 2 r 2 . . . p n r n , p i 为质数 , r i 为系数,且分解形式唯一。 \forall a > 1, a = p_1^{r_1}p_2^{r_2}...p_n^{r_n}, p_i 为质数, r_i为系数,且分解形式唯一。 ∀a>1,a=p1r1p2r2...pnrn,pi为质数,ri为系数,且分解形式唯一。
每个数都只能从最小的质因数所筛去
void eular_prime( int maxNum ) {
for ( int i = 2; i <= maxNum; ++i) {
if (!not_prime[i])
prime_table[prime_cnt++] = i;
for ( int j = 0; j < prime_cnt && i <= maxNum/ prime_table[j]; ++j) {
not_prime[ i * prime_table[j] ] = 1;
if ( i % prime_table[j] == 0)
break;
}
}
}