日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

文章目錄

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

acwing869. 試除法求約數(shù)

acwing869. 試除法求約數(shù)

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

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

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

ac代碼

#include<bits/stdc++.h> using namespace std;//用vector來存所有約數(shù) 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. 約數(shù)個數(shù)

acwing870. 約數(shù)個數(shù)

分析:
約數(shù)個數(shù)基于算術(shù)基本定理

來源于:維基百科
假設N分解質(zhì)因數(shù)(下面的p1,p2,...,pkp_1,p_2,...,p_kp1?,p2?,...,pk?都是質(zhì)數(shù))的結(jié)果是:
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的約數(shù)個數(shù)就等于(a1+1)×(a2+1)×...×(ak+1)(a_1+1)\times(a_2+1)\times...\times(a_k+1)(a1?+1)×(a2?+1)×...×(ak?+1)

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

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

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;//質(zhì)因數(shù)的次冪while(n--){//每個數(shù)都分解質(zhì)因數(shù),并統(tǒng)計因數(shù)的次冪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;//約數(shù)個數(shù):套公式(1+a1)(1+a2)...(1+ak)for(auto prime : primes) res = res*(prime.second+1) % mod;cout<<res<<endl;}

acwing871. 約數(shù)之和

acwing871. 約數(shù)之和

分析:
假設N分解質(zhì)因數(shù)的結(jié)果是:
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?

則這個數(shù)N的約數(shù)之和等于
(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??)
以上稱為“約數(shù)和定理”,在小學奧數(shù)中有應用。

補充:已知pap^apa的底數(shù)p,指數(shù)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;//質(zhì)因數(shù)的次冪while(n--){//每個數(shù)都分解質(zhì)因數(shù),并統(tǒng)計因數(shù)的次冪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; //分別是底數(shù)和指數(shù)LL t =1;//對每個質(zhì)因子,求(p^0+ p^1+...+p^k)while(a--) t = (t * p +1) %mod;res = res * t % mod;}cout<<res<<endl;}

acwing872. 最大公約數(shù)

acwing872. 最大公約數(shù)

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

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

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

輾轉(zhuǎn)相除法模板解釋:

int gcd(int a, int b){//如果b !=0 則返回 gcd(b, a mod b)//如果 b==0,則返回 a ,因為0和a的最大公約數(shù)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));}}

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。