单个素数判断
//素数判断(小数据)
int prime(int n) {
if (n == 0 || n == 1) return 0;
if (n == 2) return 1;
if (n % 2 == 0) return 0;
for (int i = 3; i * i <= n; i = i + 2)
if (n % i == 0) return 0;
return 1;
}
//Miller-Rabin(大素数判定) 单个数字n复杂度15*log(n)
int Mr[30] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
//此数组为测试用的a,这12个可测所有的long long int;
LLI Miller_Rabin(LLI n) {
if(n == 2) return true;
else if(n < 2) return false;
if(n % 2 == 0) return false;
LLI u = n - 1;
while(u % 2 == 0) u = u / 2;
LLI tempu = u;
for(int i = 0; i < 12; i ++) {
if(Mr[i] >= n) break;
u = tempu;
LLI x = Fast_power(Mr[i],u,n);//这里调用快速幂函数,p18
while(u < n) {
LLI y = (x % n) * (x % n) % n;
//注意!!!(x % n) * (x % n)很可能溢出,如果出现这种情况,用快速乘
//另外调用快速幂时也可能溢出
if(y == 1 && x != 1 && x != n - 1) return false;
x = y;
u = u * 2;
}
if(x != 1) return false;
}
return true;
}
区间素数筛
//厄拉多塞素数筛法,复杂度>O(n*log(log(n)))
bool mark[maxn];
void sieve_prime() {
memset(mark, true, sizeof(mark));
mark[0] = mark[1] = false;
for (int i = 2; i * i <= maxn; i ++)
if (mark[i])
for (int j = i * i; j < maxn; j = j + i)
mark[j] = false;
}
//欧拉素数筛法复杂度O(n)
bool isPrime[maxn];
LLI primeList[maxn],primeCount = 0;
void Eular_Sieve(LLI n) {
memset(isPrime,true,sizeof(isPrime));
isPrime[0] = false;
isPrime[1] = false;
for(int i = 2; i <= n; i ++) {
if(isPrime[i]) {
primeCount ++;
primeList[primeCount] = i;
}
for(int j = 1; j <= primeCount; j ++) {
if(i * primeList[j] > n) break;
isPrime[i * primeList[j]] = false;
if(!(i % primeList[j])) break;
}
}
}
素数筛法的应用
题目链接:
Help Hanzo
题意就是求[a,b]区间内的素数个数( 1 ≤ a ≤ b < 231, b - a ≤ 100000);
很明显,如果直接筛肯定不行……,见代码:
题意就是求[a,b]区间内的素数个数( 1 ≤ a ≤ b < 231, b - a ≤ 100000);
很明显,如果直接筛肯定不行……,见代码:
#include
#include