原題鏈結
考察: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 4using
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 ...