数学知识:质数

 试除法判定质数:

#include 
using namespace std;

bool is_prime(int x)
{
    if(x < 2) return false;
    for(int i = 2;i <= x / i;i ++)//这里是n/i,每次i++都会改变这个n/i的值,因为对i求余后不需要判断i的倍数
    {
        if(x % i == 0)
        {               //例:x:10  
            return false;//  i:2 3 4 5 6...这里不需要判断4,6...的条件,因为在前面已经判断过2,3..了
        }              //  x/i:5 3 2 2 1...最多到x/3=3时就停止了,但这里到x/3=5就停止了,判断出不是质数
    }                 //例2:x:7
    return true;      //     i:2 3
}                       //   x/i:3 2所以到x/i=3再往后就停止了,判断出是质数

int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++)
    {
        int x;
        scanf("%d",&x);
        if(is_prime(x)) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

 分解质因数:

#include
#include
using namespace std;
int main(void)
{
    int n;cin>>n;
    while(n--)
    {
        int a;cin>>a;
        for(int i=2;i<=a/i;i++)//这里是a/i,每次i++都会改变这个a/i的值,因为对i求余后不需要判断i的倍数
        {
            //i:2  2  3   3  3                        
            //a:90 45 45 15  5 3>5/3,所以直接跳出for  
            //s:0  1  0   1  2                        
            //注意:分解质因数要求必须是质数也是因数,但这里i可能取到合数比如4,不用担心,因为在while前面除以2的时候,除到不能再%2的时候才让i++到3的,所以连2都不能%了,2的倍数就自然不可能%
            if(a%i==0)
            {
                int s=0;
                while(a%i==0)
                {
                    a/=i;
                    s++;
                }
                printf("%d %d\n",i,s);  
            }
 
        }
        if(a>1) printf("%d 1\n",a); //n中最多只包含一个>sqrt(n)的质因数,当a被除以到>1找不到质因数,则a就是自己的质因数
        printf("\n");              //上例此时a为5,则结果打印:2^1 3^2 5^1,相乘就是90
    }
    return 0;    
}

筛质数:

埃式筛法:

#include 

using namespace std;

const int N = 1000010;

//primes数组用来存放质数
int primes[N];
//cnt代表质数的个数
int cnt;
//st[i], i为质数则为false否则为true,默认全是质数
bool st[N];

void get_primes(int n)
{
    for(int i = 2; i <= n; i++)
    {
        if(!st[i])//该数为质数或未判断,只要是没判断的数就是质数,因为它若是合数,则在前面就被某个质数给赋true了
        {
            primes[cnt++]=i;//cnt代表质数的个数,所以cnt++,并把该数放进数组里,方便用得到是可以拿出,但本题不需要
            for(int j = i; j<=n; j+=i)//把该质数的所有倍数都赋true代表不是质数或已经判断了
            {
                st[j]=true;
            }
        }

    }
}

int main()
{
    int n;
    scanf("%d",&n);
    get_primes(n);
    printf("%d\n",cnt);
    return 0;
}

线性筛法:

该方法就是用最小质因子判断该数是否是质数,若某个数有最小质因子了,说明该数数合数,就找下一个数;如果该数没有最小质因子就说明该数是质数。

#include 

using namespace std;

const int N = 1000010;

//primes数组用来存放质数
int primes[N];
//cnt代表质数的个数
int cnt;
//st[i], i为质数则为false否则为true,默认全是质数
bool st[N];

void get_primes(int n)
{
    //i是某个数的意思,要找2~n的所有数是否为质数
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) primes[cnt++]=i;//如果i该数是质数,则放进数组,cnt++代表质数个数加一
        
        for(int j=0;primes[j]<=n/i;j++)//primes[j]<=n/i:变形一下得到:primes[j]*i<=n,把小于n的合数都筛了
        {
            st[primes[j]*i]=true;//i无论是质数还是合数,它的质数倍数都可以赋true
            //例:i=2时,找到i的最小质因子为2,所以2*2=4被赋true
            //    i=3时,找到i的最小质因子为3,所以3*3=9被赋true
            //    i=4时,前面已经找到4为合数所以不会让上面的if出错
            //像这样,不会让任何i和合数的情况下未被赋true,而导致上面的if出错

            //当primes[j]是i的最小质因子,说明primes[j]一定是i的倍数primes[j]*i的最小质因子
            //则说明对于i的倍数primes[j+k]*i的最小质因子也是primes[j],而非primes[j+k]
            //后面的任何i的倍数都不用看了,直接break,让i++找下一个数是否为质数
            
            //当i%primes[j]!=0时,说明此时遍历到的primes[j]不是i的质因子,所以primes[j]*i的最小质因子不是primes[j]
            //可以继续找primes[j+k]的i倍是否为最小质因子
            if(i%primes[j]==0) break;
        }
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    get_primes(n);
    printf("%d\n",cnt);
    return 0;
}

你可能感兴趣的:(算法基础,算法,c++,开发语言)