數論又多又難,該從哪開始學呢?不如先思考一下下面這個問題:
對於乙個自然數n,它的因數是什麼?
一、因數的篩法
1.最簡單的暴力
相信只要你有一點數學和程式設計基礎的話,都會想到下面這個最簡單暴力的方法:
1對,只要從1到n遍歷一遍,看看是不是n的因數就解決了。int find_factor(intx)2
但是這樣的話有乙個缺點,該演算法的時間複雜度為o(n),資料稍微一大,就超時了。
2.修改後的篩法
那麼我們能不能稍微改進一下這個演算法呢?答案是可以的,我們都知道乙個數的因數一定是成對出現的,那麼對於每一組裡小的那個因數,它的大小不會超過
,利用這一點我們可以將我們的演算法做如下改進:
1這樣一來,我們的時間複雜度就變為了o(int find_factor(intx)2
10return
cnt;
11 }
),可以解決更大範圍的資料了。上面的篩法也是在大多數題目中適用的。
3.加強版篩法
但是還是有更加善良的出題人,想要繼續考察我們,這就需要我們學習專業的數學知識了。我們先來看下面兩個概念:
·分解質因數:把n表示為質數相乘的形式,如30=2×3×5。
我們可以用下面的**實現分解質因數(時間複雜度o(
)):
1 #include 2分解質因數3using
namespace
std;45
void
resolved()619
if(temp!=1) printf("
%d",temp); //
當n為質數
20return;21
}2223int
main()
24
(還有乙個時間複雜度為o(
)的演算法,日後再補)
既然這些因數都是質數,我們可以把乙個數n的分解質因數表示為:
其中,p1、p2、p3…pk是由小到大的質數,如:36=2×2×3×3=22×32。
·約數個數定理:對於乙個大於1正整數n可以分解質因數:
則n的正約數的個數就是:
其中a1、a2、a3…ak是p1、p2、p3…pk的指數。
感覺不太好理解?我們來看下面幾個例項:
(1)10=2×5=21×51
10的因子:1(20×50),2(21×50),5(20×51),10(21×51),
因子的個數=4=(1+1)×(1+1);
(2)36=2×2×3×3=22×32
36的因子:1(20×30),2(21×30),4(22×30),3(20×31),6(21×31),12(22×31),9(20×32),18(21×32),36(22×32),
因子的個數=9=(2+1)×(2+1);
看完這幾個例子,不知你感覺如何,接著我們用**來實現這個過程:
1這個方法不光可用用來求乙個數的因數的個數,還可以用來解與因數個數相關的問題。int find_factor(intx)2
12 p++;
13 cnt*=t;14}
15return
cnt;
16 }
二、約數個數定理的應用
我們來看下面幾個問題:
1.求1到n裡面約數最多的數的約數個數(n<=1018)
這個題注意資料!!!一看到這個資料我們就知道暴力是不可能實現的,那麼又如何使用上面的方法呢?如果用上面的方法進行列舉也是不可取的。
那麼我們來簡單分析下這個問題:
·我們知道每乙個數都可以用質因子的積表示,而約數的個數只與指數有關!
·我們知道pn>...>p3>p2>p1,那麼假設我們存在某乙個ak>a1 那麼我們交換pk與p1的指數,顯然約數個數不變,但是數變小了!
如:24=23×31和54=21×33。
·也就是說對於任何n,m如果pn>pm那麼an
m 要好一些。但是不是最優的,不確定,不過這已經為我們淘汰了許多不必要的情況了。
這樣使用dfs與之結合,列舉每乙個質因子的質數,保證其指數遞減,
然後我們就可以寫出**了:
1 #include 2author : houge date : 2019.5.273using
namespace
std;45
int prime[25]=; //
存一下質數
6long
long
n,ans;78
//pos代表第幾個質數,num代表目前因子的個數,multi代表目前的數,len代表迴圈的次數
9void get_num_dfs(int pos,long
long num,long
long multi,int
len)
1020
return;21
}2223int
main()
2434
return0;
35 }
update log :
2019.5.30:修正了一處錯誤。
乙個數的約數的個數 質因數分解
problem description 乙個數,如果他的素數因子只包括2,3,5,7,則稱這個數為萌數,比如,下面這些數就是前20個萌數 1,2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,24,25,27。現在給你乙個萌數,請程式設計計算它的約數的個數。比如,4是乙...
求乙個數的質因數(1個或n個)
在做 容斥原理 題時經常需要求出乙個數的質因子,而且不是所求數的位數很多,就是一次求n多數的質因子。下面分別給出兩種型別的 供拋磚引玉。第一種型別 用於每次只能求出乙個數的質因子,適用於題目中給的n的個數不是很多,但是n又特別大的情況。includeint main if n 1 應對 n 103 ...
239 判斷乙個數的所有因數的個數是偶數還是奇數
只需要你判斷因 數的個數是偶數個還是奇數個,那麼可以這麼做 濱湖 土豆 那只在計算質因數的過程 中統計一下當前質因數出現的次數,如果出現奇數次則結果為偶,然後可以立即返回 如果每個質因數的次數都是偶數,那麼結果為奇。如果該數是平方數 結果就為奇 否則就為偶了 如果乙個數是平方數,因數是奇數個 如果不...