數論 - 約數 - 試除法求約數 + 約數個數 + 約數之和

數論 - 約數 - 試除法求約數 + 約數個數 + 約數之和 + 最大公約數

1、 試出法求約數

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

輸入格式
第一行包含整數n。

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

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

數據範圍
1≤n≤100,
2≤ai≤2∗109

輸入樣例:
2
6
8
輸出樣例:
1 2 3 6 
1 2 4 8 

分析:

O(n)O(\sqrt{n})的做法,枚舉一個較小的因子,另一個直接用原數去除。

注意完全平方數只要加入一個因子。

代碼:

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

const int N=110;

int n;

void solve(int x)
{
    vector<int> p;
    for(int i=1;i<=x/i;i++)
        if(x%i==0) 
        {
            p.push_back(i);
            if(i!=x/i) p.push_back(x/i);
        }
    
    
    sort(p.begin(),p.end());
    
    for(int i=0;i<p.size();i++) cout<<p[i]<<' ';
    cout<<endl;
}

int main()
{
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        solve(x);
    }
    
    return 0;
}

2、約數個數

給定n個正整數ai,請你輸出這些數的乘積的約數個數,答案對109+7取模。

輸入格式
第一行包含整數n。

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

輸出格式
輸出一個整數,表示所給正整數的乘積的約數個數,答案需對109+7取模。

數據範圍
1≤n≤100,
1≤ai≤2∗109

輸入樣例:
3
2
6
8
輸出樣例:
12

aA=P1a1P2a2...PkakA(a1+1)(a2+1)...(ak+1)正整數a的約數個數:\\由算術基本定理,設A=P_1^{a_1}P_2^{a_2}...P_k^{a_k},則A的約數個數爲(a_1+1)(a_2+1)...(a_k+1)。

AA=P1b1P2b2...Pkbkbi[0,ai]i[1,k]說明: \\設A的一個約數A'=P_1^{b_1}P_2^{b_2}...P_k^{b_k},其中b_i∈[0,a_i],i∈[1,k]。

k(b1,b2,...,bk)Abiai+1\\每一個k元組(b_1,b_2,...,b_k)均能對應A的一個約數,對於每個b_i都有a_i+1種取值,

kACa1+11Ca2+11...Cak+11=(a1+1)(a2+1)...(ak+1)根據乘法原理,不同的k元組的個數即A的所有約數的個數爲C_{a_1+1}^1C_{a_2+1}^1...C_{a_k+1}^1=(a_1+1)(a_2+1)...(a_k+1)。

具體落實:

A問題轉化分解A的所有質因數並保存每個質因數的指數,再用公式。

代碼:

#include<iostream>
#include<unordered_map>

#define ll long long
#define x first
#define y second

using namespace std;

const int mod=1e9+7;

int n;
unordered_map<int,int> P;

int main()
{
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        for(int i=2;i<=x/i;i++)
            while(x%i==0)
            {
                x/=i;
                P[i]++;
            }
        if(x>1) P[x]++;
    }
    
    ll res=1;
        for(auto p: P)
            res=res*(p.y+1)%mod;
        
    cout<<res<<endl;
    
    return 0;
}

3、約數之和

給定n個正整數ai,請你輸出這些數的乘積的約數之和,答案對109+7取模。

輸入格式
第一行包含整數n。

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

輸出格式
輸出一個整數,表示所給正整數的乘積的約數之和,答案需對109+7取模。

數據範圍
1≤n≤100,
1≤ai≤2∗109

輸入樣例:
3
2
6
8
輸出樣例:
252

aA=P1a1P2a2...PkakAi=1kj=0aiPij正整數a的約數個數:\\由算術基本定理,設A=P_1^{a_1}P_2^{a_2}...P_k^{a_k},則A的約數之和爲\prod_{i=1}^k\sum_{j=0}^{a_i}P_i^j。

(P10+P11+...+P1a1)(P20+P21+...+P2a2)...(Pk0+Pk1+...+Pkak)即(P_1^0+P_1^1+...+P_1^{a_1})(P_2^0+P_2^1+...+P_2^{a_2})...(P_k^0+P_k^1+...+P_k^{a_k})

說明:
AA=P1b1P2b2...Pkbkbi[0,ai]i[1,k]設A的一個約數A'=P_1^{b_1}P_2^{b_2}...P_k^{b_k},其中b_i∈[0,a_i],i∈[1,k]。

k(b1,b2,...,bk)APixxai+1每一個k元組(b_1,b_2,...,b_k)均能對應A的一個約數,對於每個質因子P_i^{x},x均有a_i+1種選法,

k{Pi0Pi1...Piai}pixi[1,k],x[0,ai]現需在k 個形如\{P_i^0,P_i^1,...,P_i^{a_i}\}的集合中選一個p_i^{x},i∈[1,k],x∈[0,a_i],

kP1x1P2x2...Pkxk:選k次,每次對應一個約數P_1^{x_1}P_2^{x_2}...P_k^{x_k},最終求和結果爲: (P10+P11+...+P1a1)(P20+P21+...+P2a2)...(Pk0+Pk1+...+Pkak)(P_1^0+P_1^1+...+P_1^{a_1})(P_2^0+P_2^1+...+P_2^{a_2})...(P_k^0+P_k^1+...+P_k^{a_k})

具體落實:

A①、首先對A分解質因數,並記錄每個質因數的指數,用一個哈希表存儲。

Pi0+Pi1+Pi2+...+Piait=tPi+1ai+1②、求P_i^{0}+P_i^{1}+P_i^{2}+...+P_i^{a_i}可以用迭代來做,t=t*P_i+1,迭代a_i+1次。\\\qquad當然也可以用等比數列求和公式、分治等方法。

代碼:

#include<iostream>
#include<unordered_map>

#define ll long long
#define x first
#define y second

using namespace std;

const int mod=1e9+7;

int n;
unordered_map<int,int> prime;

int main()
{
    cin>>n;
    while(n--)
    {
        int x;
        cin>>x;
        for(int i=2;i<=x/i;i++)
            while(x%i==0)
            {
                x/=i;
                prime[i]++;
            }
        if(x>1) prime[x]++;
    }
    
    ll res=1;
    for(auto p : prime)
    {
        ll t=0;
        for(int i=0;i<=p.y;i++)
            t=(t*p.x+1)%mod;
        res=res*t%mod;
    }
    
    cout<<res<<endl;
    
    return 0;
    
}

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