每日四題打卡-4.3:判質數/分解質因數/篩質數/求約數

判質數

質數概念:在大於1的整數中,如果只包含1和本身這兩個約數,就被稱爲質數或者叫素數。

質數性質:如果d/n能整除,那麼n/d / n也能整除。

比如n = 12, 3和4都是他的約數,n的約數都是成對出現的  。在枚舉的時候我們可以只枚舉沒對較小的一個就可以了。

給定n個正整數aiai,判定每個數是否是質數。

輸入格式

第一行包含整數n。

接下來n行,每行包含一個正整數aiai。

輸出格式

共n行,其中第 i 行輸出第 i 個正整數aiai是否爲質數,是則輸出“Yes”,否則輸出“No”。

數據範圍

1≤n≤1001≤n≤100,
1≤ai≤2∗1091≤ai≤2∗109

輸入樣例:

2
2
6

輸出樣例:

Yes
No
#include <iostream>
using namespace std;

bool is_prime(int x)
{
    if(x < 2) return false;
    for (int i = 2; i <= x / i; i ++)
        if (x % i == 0) return false;
    return true;
}
int main()
{
    int n;
    cin >> n;
    while(n --)
    {
        int x;
        cin >> x;
        if(is_prime(x)) puts("Yes");
        else puts("No");
    }
}

分解質因數

概念:從小到大枚舉所有的數。

給定n個正整數aiai,將每個數分解質因數,並按照質因數從小到大的順序輸出每個質因數的底數和指數。

輸入格式

第一行包含整數n。

接下來n行,每行包含一個正整數aiai。

輸出格式

對於每個正整數aiai,按照從小到大的順序輸出其分解質因數後,每個質因數的底數和指數,每個底數和指數佔一行。

每個正整數的質因數全部輸出完畢後,輸出一個空行。

數據範圍

1≤n≤1001≤n≤100,
1≤ai≤2∗1091≤ai≤2∗109

輸入樣例:

2
6
8

輸出樣例:

2 1
3 1

2 3
//步驟:求a能被i整除的最小的數i(從2開始遍歷),並且使用while循環用d來存底數,a/=i繼續往下除,直到除不下爲止。
//      輸出累除的結果i和d
#include <iostream>
using namespace std;
int n;
void divide(int a)
{
    for (int i = 2; i <= a / i; i ++)//這裏是a/i
    {
        if (a % i == 0)
        {
            int d = 0;//存底數
            while(a%i == 0)
            {
                d ++;
                a/= i;
            }
            cout << i << " " << d << endl;//這裏是輸出i,d。注意i實際上是指數
        }
    }
    //每個質因數的底數和指數,每個底數和指數佔一行
    if (a > 1) cout << a << " " << 1 << endl;
    puts("");
}
int main()
{
    cin >> n;
    while(n --)
    {
        int a;
        cin >> a;
        divide(a);
    }
    return 0;
}

 篩質數

~n中質數有n/ln(n)個質數

按順序刪除每個數的倍數,最後剩下的就是質數。

給定一個正整數n,請你求出1~n中質數的個數。

輸入格式

共一行,包含整數n。

輸出格式

共一行,包含一個整數,表示1~n中質數的個數。

數據範圍

1≤n≤1061≤n≤106

輸入樣例:

8

輸出樣例:

4
//步驟:1、循環i = 2,i <= n,i ++;2、當前數沒有被篩過,則標記它是個質數;3、//將n的倍數刪除掉
#include<iostream>
using namespace std;
const int N = 1000010;
int prime[N], cnt;

bool st[N];//標誌他是否是質數
int n;
//樸素做法
// void get_primes(int n)
// {
//     for (int i = 2; i <= n; i ++)//不需要n / i
//     {
//         //步驟要記住!!!!
//         if (!st[i])prime[cnt ++ ] = n;//當前數沒有被篩過,則是個質數
//         for (int j = i + i; j <= n; j +=i) //將n的倍數刪除掉
//             st[j] = true;//標記爲true
//     }
// }

//埃式篩法-O(nloglogn)
// void get_primes(int n) {
//     for(int i = 2; i <= n; i++) {
//         if(!st[i]){ 
//             prime[cnt++] = i;
//             //跟樸素不一樣的事吧這個for循環放到了這裏,而且循環是從j = i,j+=i來做
//             for(int j = i; j <= n; j += i)
//                 st[j] = true;
//         }
//     } 
// }

//線性篩法-O(n), n = 1e7的時候基本就比埃式篩法快一倍了
//算法核心:x僅會被其最小質因子篩去
void get_primes(int x) {
    for(int i = 2; i <= x; i++) {
        if(!st[i]) prime[cnt++] = i;//找到質數
        for(int j = 0; prime[j] <= x / i; j++) {//從0開始找j倍數
            //對於任意一個合數x,假設pj爲x最小質因子,當i<x/pj時,一定會被篩掉
            st[prime[j]*i] = true;//倍數直接標記
            if(i % prime[j] == 0) break;
            /*
            1.i%pj == 0, pj定爲i最小質因子,pj也定爲pj*i最小質因子
            2.i%pj != 0, pj定小於i的所有質因子,所以pj也爲pj*i最小質因子
            */
        }
    }
} 


int main()
{
    cin >> n;
    get_primes(n);
    cout << cnt << endl;
    return 0;
}

求約數

使用試除法求一個數的所有約數。

1、從小到大枚舉所有約數

2、只枚舉每一對約數較小的

3、如果i != n / i,才加進去

給定n個正整數ai,對於每個整數ai,請你按照從小到大的順序輸出它的所有約數。

輸入格式

第一行包含整數n。

接下來n行,每行包含一個整數aiai。

輸出格式

輸出共n行,其中第 i 行輸出第 i 個整數aiai的所有約數。

數據範圍

1≤n≤100,
2≤ai≤2∗10^9

輸入樣例:

2
6
8

輸出樣例:

1 2 3 6 
1 2 4 8
//步驟:1、學會用vector容器,vector<int> a;2、如果是一個約數則存起來res.push_back(i);
//3、可能會出現n = i * i的情況兩個餘數相同的情況,所以需要判斷一下if (i != n / i) res.push_back(n / i);
//4最後將約數排個序sort(res.begin(), res.end());   
#include <iostream>
#include <vector>//存一個數的所有約數
#include <algorithm>
using namespace std;

vector<int> get_divisors(int n)
{
    vector<int> res;
    for (int i = 1; i <= n / i; i ++)
        if (n % i == 0)//如果是一個約數,則存起來
        {
            res.push_back(i);
            if (i != n / i) res.push_back(n / i);//可能會出現n = i * i的情況兩個餘數相同的情況,所以需要判斷一下
        }
    //最後將約數排個序
    sort(res.begin(), res.end());
    return res;
}

int main()
{
    int n;
    cin >> n;
    while(n --)
    {
        int x;
        cin >> x;
        auto res = get_divisors(x);//dedaox所有的約數
        //循環遍歷所有約數
        for(auto t : res) cout << t << ' ';
        cout << endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章