质数相关问题(一)

数论之质数问题1

问题1:判断n是不是质数

#include

using namespace std;

bool isprime(int n)
{
    if(n<2)return false;
    for(int i=2;i<=n/i;i++)//这里写成n/i比i*i<=n和sqrt(n)更好一些,因为用i*i的话,当i过大容易越界,而算sqrt(n)速度比较慢
    {
        if(n%i==0)return false;
    }
    return true;
}

int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int m;
        cin>>m;
        if(isprime(m))cout<<"Yes"<<endl;
        else 
        {
            cout<<"No"<<endl;
        }
        
    }
    return 0;
}

问题2:分解质因数,将一个数字分解为它的质数乘积
给定 n 个正整数 ai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。

输入格式
第一行包含整数 n。

接下来 n 行,每行包含一个正整数 ai。

输出格式
对于每个正整数 ai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。

每个正整数的质因数全部输出完毕后,输出一个空行。

数据范围
1≤n≤100,
2≤ai≤2×109
输入样例:
2
6
8
输出样例:
2 1
3 1

2 3
思路,用比n小的数去除n,如果能整除,就进行整除,同时n也会变小,这里值得注意的是,分解之后比根号n大的质数最多只有一个(反证法容易证明),因此我们只要用小于根号n的数来试除n就可以了,最后再判断一下n是否大于1,如果大于1的话,那么这个数也是初始n分解成的质因数。
代码如下:

#include 
#include 
#include 

using namespace std;

void divide(int n)
{
    for(int i=2;i<=n/i;i++)
    {
        if(n%i==0)
        {
            int s=0;
            while(n%i==0)
           {
              n=n/i;
              s++;
           }
           printf("%d %d\n",i,s);
        }
    }
    if(n>1)printf("%d %d\n",n,1);
    printf("\n");
}

int main()
{
    int m;
    cin>>m;
    while (m-- )
    {
        int n;
        cin>>n;
        divide(n);
    }
    return 0;
}

问题2:求1-n有多少个质数
方法一:
线性筛:就是首先把2的全部倍数筛选掉,再把3的全部倍数筛选掉
,再把4的全部倍数筛选掉,把i-1的全部倍数筛选掉,如果筛选到i,
发现i没有被筛选掉,这就说明i不是[2,i-1]的之中任何一个数字的倍数,说明i是质数,否则i不是质数,然后再用i去筛后面的数字。
时间复杂度分析:
用2去筛选的时候遍历了n/2次,用3筛选的时候遍历了n/3次,用i去筛选的时候遍历了n/i次。
总的时间复杂度就是
n/2+n/3+n/4+n/5+…+n/n=nln(n);(把n提取出来是个调和级数,调和级数约等于ln(n)+c);

#include 
#include 
#include 

using namespace std;
const int N=1000010;
int ans;
bool st[N];

void divide(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
        {
            ans++;
        }
        for(int j=i+i;j<=n;j=j+i)st[j]=true;
    }
}

int main()
{
    int n;
    cin>>n;
    divide(n);
    cout<<ans;
    return 0;
}

方法2:要学会方法2,首,先要学会方法1,首先由唯一分解定理知道,一个合数(非质数)必然可以分解为比它小的一个质数和一个大于等于2的数的乘积。因此我们不需要用比i小的每一个数字去筛来判断i是否是质数,我们只需要用小于i的质数去筛就可以了。因此时间复杂度降低了,由质数定理知,1-n大约有n/ln(n)个质数,因此时间复杂度为o(nln(ln(n)))约等于o(n);
注:在代码上只是把筛i倍数的那层for循环放到了if条件语句里面了,因为if语句一旦执行,就说明当前的i是质数。

#include 
#include 
#include 

using namespace std;
const int N=1000010;
int ans;
bool st[N];

void divide(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
        {
            ans++;
            for(int j=i+i;j<=n;j=j+i)st[j]=true;
        }
    }
}

int main()
{
    int n;
    cin>>n;
    divide(n);
    cout<<ans;
    return 0;
}

你可能感兴趣的:(数论,c++,算法,c语言)