质因数算法(C/C++)

目录

1  分解质因数

2  打印质数表

2.1  O(n^2)算法(暴力法)

2.2  O(nlogn)算法(埃氏筛)

2.3  O(n)算法(线性筛)

3  计算因数和


1  分解质因数

#include <bits/stdc++.h>
using namespace std;
int num,temp;
int main()
{
	scanf("%d",&num);
	temp=num;//保护 
	for(int i=2;i<=temp;i++)
	{
		while(num%i==0)
		{
			printf("%d ",i);
			num/=i;
		}
	}
	return 0;
}

说明:这里不需要担心没有筛选质数的问题,因为是从小到大循环,不可能存在分解出合数的情况(例如:2第一个循环,所有2的倍数都已经被筛选掉了,后续循环不可能再有2的倍数被num整除)

2  打印质数表

2.1  O(n^2)算法(暴力法)

两层循环,第一层循环i遍历大于等于2的所有数,第二层循环遍历大于1小于i的所有数j,判断i%j!=0一直成立,则该数为质数

这种方法虽然思路简单,但时间复杂度有时不能满足题目要求

2.2  O(nlogn)算法(埃氏筛)

定理:一个质数*任何一个不为1的正整数=合数

有了定理之后,就可以通过定理优化代码降低时间复杂度,下面是具体思路

Eratosthenes筛选方法(Eratosthenes Sieve Method)

假设有一个筛子存放1~N,例如:

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 .........N

先将  2的倍数  筛去:

2 3 5 7 9 11 13 15 17 19 21..........N

再将  3的倍数  筛去:

2 3 5 7 11 13 17 19..........N

 之后,再将5的倍数筛去,再来将7的质数筛去,再来将11的倍数筛去........,如此进行到最后留下的数就都是质数,这就是Eratosthenes筛选方法(Eratosthenes Sieve Method)。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int primes[1000000];
int cnt;
bool notprime[1000000];

void set_prime()
{
	notprime[1]=true;
	for(int i=2;i<1000000;i++)
	{
		if(!notprime[i])
		{
			primes[++cnt]=i;
		}
		for(ll j=(ll)i*i;j<1000000;j+=i)//保证每一个遍历的值都没被筛过
		{
			notprime[j]=true;
		}
	}
} 

int main()
{
	set_prime();
	for(int i=1;i<=cnt;i++)
	{
		cout<<primes[i]<<endl;
	}
	return 0;
}

 模拟发现,有一些数被筛了不止一次,可能还有更优解

2.3  O(n)算法(线性筛)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int primes[1000000];
bool notprime[1000000];
int cnt,n;
int main()
{
	cin>>n;//打印范围 
	for(int i=2;i<=n;i++)
	{
		if(!notprime[i])	primes[++cnt]=i;
		for(int j=1;j<=cnt&&i*primes[j]<=n;j++)
		{
			notprime[i*primes[j]]=true;
			if(i%primes[j]==0)	break;
		}
	}
	for(int i=1;i<=cnt;i++)
	{
		cout<<primes[i]<<endl; 
	}
	return 0;
} 
	

3  计算因数和

直接上例题:

寻找完数
【问题描述】
完数是指一个整数恰好等于它的因子和(除自身外),则称这个数为完数。从键盘先后输入两个不大于999的正整数m和n,若m>n,则交换两数,然后求m和n之间(m和为正数且m≤n)的所有完数
【输入形式】
先后输入两个正整数m和n,用逗号分隔
【输出形式】
输出所有完数,每两个数之间用号分隔若输入非法,则输出error
【样例输入】
1,2000 
【样例输出】
6,28,496
【样例说明】

【评分标准】
正确性

注意:没有考虑输出的逗号(处理方法:第一个数单独输出)

#include<bits/stdc++.h>
using namespace std;
int m,n,j,i;

bool factorSum(int n)
{
	int sum=0;
    for (i=1;i*i<=n;i++)
	{
        if (n%i==0&&n!=i)
		{
            if (i==1||i*i==n) sum+=i;
            else	sum+=i+n/i;
        }
    }
    return j==sum;
}

int main()
{
	scanf("%d,%d",&m,&n);
	if(m<=0||n<=0||m>9999||n>9999)
	{
		printf("error");
		return 0;
	}
	if(m>n)
	{
		swap(m,n);
	}
	for(j=m;j<=n;j++)
	{
		if(factorSum(j)) printf("%d,",j);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_71934846/article/details/129732458
今日推荐