数学知识--- 质数、约数、分解质因数

质数

  • 大于1的整数中,如果只包含1和它本身这两个约数,就被称为质数,也叫素数
  • 对于一个足够大的整数N,不超过N的质数大约有N/lnN个,即每lnN个数中大约有1个质数

质数的判定

  • 试除法---时间复杂度O(sqrt(n))
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; 

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("");
}
posted @ 2020-07-06 15:26  chstor  阅读(661)  评论(0编辑  收藏  举报