AcWing 1296 聰明的燕姿

2022-06-07 21:18:11 字數 1216 閱讀 8373

原題鏈結

考察:dfs+約數

錯誤思路:

倍數法求出所有約數,n要開到1e9必然mle且tle

正確思路:

觀察約數之和的式子 s = (1+p1+p1

2+p1

3+..)*(1+p2+p2

2+p2

3+...) ,要滿足能夠這種性質的數在1~2e9內較少.再繼續觀察,假設p全為2,(1+2)*(1+2+22)*(1+2+22+23)...當上面的指數到達7時,就已經達到了1e8的級別.也就是說組成s的項數較少,這代表我們可以用dfs.

for

(列舉質數)

for(列舉指數)

if(s%列舉和==0) dfs(下乙個);

但是注意到s=2e9,也就是答案可能在1~s-1之間,如果我們列舉質數,需要列舉到s/log(s)也就是1e8的級別.這代表我們還需要優化,可以發現我們要列舉的大質數,基本是在1+p的形式裡,也就是當s很大的時候,如果特別討論1+p可以避免列舉大質數.現在拋去s=1+p的形式,剩下的是s= 1+p+p2+...這裡的p的指數至少為2,這代表我們可以列舉到√s範圍的質數.一下就把109範圍的質數壓到105.此時的時間複雜度是10*100*√s<1e8

這題總結一下就是如果你沒發現滿足該性質的數很少基本沒救

1 #include 2 #include 3 #include 4

using

namespace

std;

5 typedef long

long

ll;6

const

int n = 100010;7

intprime[n],cnt,len,call[n];

8bool

st[n];

9void getprime(int

n)1019}

20}21bool isprime(int

s)22

28void dfs(int last,int now,int

s)29

35if(s-1>prime[last]&&isprime(s-1)) dfs(last,now*(s-1),1

);36

for(int i=last+1;prime[i]<=s/prime[i];i++)

3742}43

intmain()

4456

return0;

57 }

acWing 1296 聰明的燕姿

用到了算數基本定理的思想,尤拉篩的不記錄最小質因子的板子,另外在優化dfs的時候還用到了小學生求素數的一點小思想,下面我們簡單說一下思路和分析幾個問題。思路 正約數之和等於s的數,容易想到直接列舉每乙個質數與每乙個質數的數量,然後進行優化。第乙個問題 尤拉篩存質數的陣列到底開多大?這個問題,誰一開始...

AcWing1296 聰明的燕姿

解題思路 首先我們肯定要用到約數之和定理 但是有個問題就是要怎麼用 根據經驗得知,約數最多也就六七個左右,不然直接就超了s的範圍。所以我們考慮用爆搜來做 但是用爆搜的話還是要優化一下思路和用什麼順序去搜尋。順序 按照p和 的順序來列舉 一旦s 這個當前的乘積 0 dfs的精髓 那才能跳到下一層迴圈因...

AcWing 1296 聰明的燕姿

算術基本定理 任何乙個大於1的自然數 n,如果n不為質數,那麼n可以唯一分解成有限個質數的乘積 則可以對s進行分解質因數 s p1 p2 pn 根據約數之和 sum 1 p1 1 p1 2 p1 1 pn 1 pn 而任何約數之和為s的數一定可以表示為約束之和公式的形式,即 s sum 因此除了1 ...