算術基本定理:任何乙個大於1的自然數 n,如果n不為質數,那麼n可以唯一分解成有限個質數的乘積
則可以對s進行分解質因數 \(s = p1^ + p2^ + ... + pn^\)
根據約數之和 \(sum = (1 + p1^1 + p1^2 + ... + p1^) * ... * (1 + pn^1 + ... + pn^)\)
而任何約數之和為s的數一定可以表示為約束之和公式的形式, 即\(s = sum\)
因此除了1 + p這種形式之外, p一定小於\(\sqrt\), 因此篩質數只需要篩到\(\sqrt\)就行
容易判斷,乘的項不會超過十項,因此可以採用暴搜的方法列舉出所有滿足約數之和為s的數。
暴蒐時,保證p是遞增的,避免重複搜尋。
注意:相對於約數之和公式,所求的答案是\(ans = p1^ * ... * pk^\)
#include#include#includeusing namespace std;
const int n = 5e4 + 10;
int primes[n], cnt;
bool st[n];
int ans[n], len;
void get(int n) //線性篩
}}bool judge(int x) //試除法判斷x是否是質數
void dfs(int last, int sum, int s) //暴搜 last是上次列舉的質數下標 sum是當前讓剩下項乘積為s的數的數值
if(s - 1 > (last >= 0 ? primes[last] : 1) && judge(s - 1)) ans[len ++] = sum * (s - 1);
for(int i = last + 1 ; primes[i] <= s / primes[i] ; i ++)
}int main()
}return 0;
}
acWing 1296 聰明的燕姿
用到了算數基本定理的思想,尤拉篩的不記錄最小質因子的板子,另外在優化dfs的時候還用到了小學生求素數的一點小思想,下面我們簡單說一下思路和分析幾個問題。思路 正約數之和等於s的數,容易想到直接列舉每乙個質數與每乙個質數的數量,然後進行優化。第乙個問題 尤拉篩存質數的陣列到底開多大?這個問題,誰一開始...
AcWing1296 聰明的燕姿
解題思路 首先我們肯定要用到約數之和定理 但是有個問題就是要怎麼用 根據經驗得知,約數最多也就六七個左右,不然直接就超了s的範圍。所以我們考慮用爆搜來做 但是用爆搜的話還是要優化一下思路和用什麼順序去搜尋。順序 按照p和 的順序來列舉 一旦s 這個當前的乘積 0 dfs的精髓 那才能跳到下一層迴圈因...
AcWing 1296 聰明的燕姿
原題鏈結 考察 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 當...