质数
- 大于1的整数中,如果只包含1和它本身这两个约数,就被称为质数,也叫素数
- 对于一个足够大的整数N,不超过N的质数大约有N/lnN个,即每lnN个数中大约有1个质数
质数的判定
bool isprime(int x){
if(x < 2) return 0;
for(int i=2;i <= x/i;i++){
if(x%i==0)
return false;
}
return true;
}
质数的筛选
埃氏筛法
- 对于每个数x,只要从x * x开始,把x * x,(x + 1) * x,...,[N/x] * x标记为合数即可
- 时间复杂度O(nloglogN)
//st[N] 合数标记
void get_primes(int n){
memset(st,0,sizeof st);//合数标记
for(int i = 2; i <= n; i ++ ){
if(st[i]) continue;
primes[++ cnt] = i;//primes[]存储所有素数
for(int j = i; j <= n/i; j ++) st[i * j] = true;
}
}
线性筛法
- 每个合数i * p 只会被它的最小质因子p筛一次,时间复杂度为O(N)
- n = 1e7的时候基本就比埃式筛法快一倍了
int primes[N],cnt;//存储所有质数
int st[N];//记录每个数的最小质因子
void get_primes(int n){
memset(st,0,sizeof st);//最小质因子标记
for(int i = 2; i <= n; i ++ ){
if(!st[i]) st[i] = i,primes[++ cnt] = i;
for(int j = 1; j <= cnt; j ++ ){
//i有比prime[j]更小的质因子,或者超出n的范围,停止循环
if(primes[j] > st[i] || primes[j] > n/i) break;
//primes[j]是合数i*primes[j]的最小质因子
st[i * primes[j]] = primes[j];
}
}
}
for(int i = 1; i <= cnt; i ++ ) cout<<primes[i]<<endl;
分解质因数
- 任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作:N= p1^c1 * p2^c2 * pm^cm (pi都是质数)
试除法
- 2 ~[根号N]的每个数d,若d能整除N,则从N中除掉所有的因子d,同时累计除去d的个数
- 一个合数的因子一定在扫描到这个合数之前就从N中被除掉了,能整除N的一定是质数
- 特别地,若N没有被任何2~[根号N]的数整除,则N是质数
//primes[N],cnt 存储所有质因数
//c[N] 存储每个质因数的出现的个数
void divide(int n){
for(int i = 2; i <= n/i; i ++ ){
if(n % i == 0){
primes[++ cnt] = i,c[m] = 0;
while(n % i == 0) n/=i,c[m] ++;
}
}
if(n > 1) primes[++ cnt] = n,c[m] = 1;
for(int i = 1; i <= cnt; i ++ ) cout<<primes[i]<<"^"<<c[i]<<endl;
}
约数
- 若整数n除以整数d的余数为0,即d能整除n,则称d是n的约数,n是d的倍数,记为d|n
求N的正约数集合——试除法
- 约数总是成对出现(除了完全平方数,根号N会单独出现)
- 一个整数N的约数个数上界为2*[根号N]
int factor[N],cnt;
int divide(int n){
cnt = 0;
for(int i = 1; i <= n/i; i ++ ){
if(n % i == 0){
factor[++ cnt] = i;
if(i != n/i) factor[++ cnt] = n/i;
}
}
}
for(int i = 1; i <= cnt; i ++ ) cout<<factor[i]<<endl;
![](https://img2020.cnblogs.com/blog/2054252/202011/2054252-20201114215616959-656593959.png)
1~N每个数的正约数集合---倍数法
- 采用倍数法,时间复杂度为O(NlogN)
- 1~N每个数的约数个数总和大约为NlogN
vector<int > factor[N];
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= n/i; j ++ )
factor[i * j].push_back(i);
}
for(int i = 1; i <= n; i ++ ){
for(int j = 0; j < facotr[i].size(); j ++ ){
printf("%d ",factor[i][j]);
}
puts("");
}