日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

算法刷题-数论-试除法求约数、约数个数、约数之和、最大公约数(辗转相除法)

發布時間:2025/4/5 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法刷题-数论-试除法求约数、约数个数、约数之和、最大公约数(辗转相除法) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • acwing869. 試除法求約數
      • acwing870. 約數個數
      • acwing871. 約數之和
      • acwing872. 最大公約數

acwing869. 試除法求約數

acwing869. 試除法求約數

試除法求一個數的所有約數:從小到大枚舉,如果當前枚舉的數是原數的約數,就記錄下來(或者輸出)。
優化:如果 d能整除n的話,那么 n/d也能整除n;比如,3能整除6,那么 6/3=2,2也能整除6.因為約數是一對一對出現的。

這里的的優化是只枚舉較小的約數d,另一個可以直接n/d算出來,這樣的話只需要枚舉到n\sqrt{n}n?即可。

試除法求一個數所有約數,時間復雜度O(n)O(\sqrt{n})O(n?)

ac代碼

#include<bits/stdc++.h> using namespace std;//用vector來存所有約數 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);//邊界情況,i == n/i,只放一個就可以if(i != n/i) res.push_back(n/i);}}sort(res.begin(),res.end());return res; } int main(){int n;cin >> n;while(n--){int a;cin >> a;vector<int > res = get_divisors(a);//下面這種寫法,避免行末空格,在PAT這種OJ上會卡掉!cout<<res[0];for(int i;i<res.size(); i++) cout<<" "<<res[i];cout<<endl;}}

acwing870. 約數個數

acwing870. 約數個數

分析:
約數個數基于算術基本定理

來源于:維基百科
假設N分解質因數(下面的p1,p2,...,pkp_1,p_2,...,p_kp1?,p2?,...,pk?都是質數)的結果是:
N=p1a1×p2a2×...×pkakN={p_1}^{a_1}\times{p_2}^{a_2}\times...\times{p_k}^{a_k}N=p1?a1?×p2?a2?×...×pk?ak?

則N的約數個數就等于(a1+1)×(a2+1)×...×(ak+1)(a_1+1)\times(a_2+1)\times...\times(a_k+1)(a1?+1)×(a2?+1)×...×(ak?+1)

所以這道題,最后的那個數N是給定的所有數的乘積,對N進行分解因式,其實,可以對乘起來之前的每一個數分解質因數,相同的因數,次冪累加起來。

用到分解質因數的知識,請移步筆者另一篇文章:
算法刷題-數論-質數的判定、分解質因數、篩質數中分解質因數的知識點。

ac代碼

#include<bits/stdc++.h> using namespace std;const int mod =1e9 + 7; typedef long long LL;int main(){int n;cin >> n;unordered_map<int,int> primes;//質因數的次冪while(n--){//每個數都分解質因數,并統計因數的次冪int x;cin >> x;for(int i=2; i<= x/i ;i++){while( x % i ==0 ){x/=i;primes[i] ++;}}if(x >1)primes[x] ++;}LL res =1;//約數個數:套公式(1+a1)(1+a2)...(1+ak)for(auto prime : primes) res = res*(prime.second+1) % mod;cout<<res<<endl;}

acwing871. 約數之和

acwing871. 約數之和

分析:
假設N分解質因數的結果是:
N=p1a1×p2a2×...×pkakN={p_1}^{a_1}\times{p_2}^{a_2}\times...\times{p_k}^{a_k}N=p1?a1?×p2?a2?×...×pk?ak?

則這個數N的約數之和等于
(p10+p11+p12+...+p1a1)×(p20+p21+p22+...+p2a2)×...×(pk0+pk1+pk2+...+pkak)(p_{1}^{0}+p_{1}^{1}+p_{1}^{2}+...+p_{1}^{a_{1}})\times(p_{2}^{0}+p_{2}^{1}+p_{2}^{2}+...+p_{2}^{a_{2}})\times...\times(p_{k}^{0}+p_{k}^{1}+p_{k}^{2}+...+p_{k}^{a_{k}})(p10?+p11?+p12?+...+p1a1??)×(p20?+p21?+p22?+...+p2a2??)×...×(pk0?+pk1?+pk2?+...+pkak??)
以上稱為“約數和定理”,在小學奧數中有應用。

補充:已知pap^apa的底數p,指數a,如何快速求出p0+p1+...+pap^0+ p^1+...+p^ap0+p1+...+pa

有以下代碼

//求(p^0+ p^1+...+p^a)的代碼 int t =1; while(a--) t = t* p +1;

ac代碼

#include<bits/stdc++.h> using namespace std;const int mod =1e9 + 7; typedef long long LL;int main(){int n;cin >> n;unordered_map<int,int> primes;//質因數的次冪while(n--){//每個數都分解質因數,并統計因數的次冪int x;cin >> x;for(int i=2; i<= x/i ;i++){while( x % i ==0 ){x/=i;primes[i] ++;}}if(x >1)primes[x] ++;}LL res =1;for(auto prime : primes){int p = prime.first , a = prime.second; //分別是底數和指數LL t =1;//對每個質因子,求(p^0+ p^1+...+p^k)while(a--) t = (t * p +1) %mod;res = res * t % mod;}cout<<res<<endl;}

acwing872. 最大公約數

acwing872. 最大公約數

輾轉相除法的核心:
(a,b)的最大公約數 =(b,a mod b)的最大公約數

amodb=a??ab?b=a?kb,k為常數a\ mod \ b = a-\lfloor \frac{a}{b}\rfloor b =a - kb,k為常數a?mod?b=a??ba??b=a?kb,k
怎么證明呢?思想是證明(a,b)的公約數 和(b, a mod b)的公約數完全相同,則它們的最大公約數也相同。等價表述是,任何1個(a,b)的公約數,都是(b,a mod b)的公約數;反過來,任何1個(b,a mod b)的公約數,都是(a,b)的公約數,那么(a,b)的公約數 和(b, a mod b)的公約數完全相同。

具體證明過程略,提示:會用到數論里面的結論,若d能整除a,d能整除b,則d整除k1a+k2b,k1,k2k_1a+k_2b,k_1,k_2k1?a+k2?bk1?,k2?是常數。

輾轉相除法模板解釋:

int gcd(int a, int b){//如果b !=0 則返回 gcd(b, a mod b)//如果 b==0,則返回 a ,因為0和a的最大公約數areturn b ? gcd(b, a %b) :a; }

AC代碼

#include<bits/stdc++.h> using namespace std;int gcd(int a, int b){return b ? gcd(b, a %b) :a; } int main(){int n;cin >> n;while(n--){int a, b;scanf("%d%d",&a,&b);printf("%d\n",gcd(a,b));}}

總結

以上是生活随笔為你收集整理的算法刷题-数论-试除法求约数、约数个数、约数之和、最大公约数(辗转相除法)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。