數論_質數_BZOJ1053_反質數
阿新 • • 發佈:2018-11-28
思路分析:
可以證明, 以下結論1, 2, 3成立.
結論1: 不超過N的最大的反質數為2...N中具有最多約數的最小的數(直接根據反質數定義即可證明此結論)
結論2: 當N <= 2000000000時, N的不同質因數的個數不超過10(根據最小的11個質數的乘積為可證明此結論)
結論3: 將不超過N的最大的反質數A分解質因數後滿足A = (參考氣泡排序交換的過程, 對於任意不滿足
下面給出基於結論1, 2, 3的AC程式碼:
//BZOJ1053_反素數 #include <iostream> #include <vector> #include <algorithm> #define mp make_pair #define fi first #define se second using namespace std; typedef pair<int, int> pii; const int arr[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; int N; int resval, respow;// resval: 反素數值, respow: resval約數的個數 //path.first:質因數值, path.second: 冪次, mul: path中元素的乘積 void dfs(vector<pii> &path, int mul){ if(mul * 2ll > N){//注意此處應使用2ll, 直接用int型2會超出int的最大值 int cnt = 1; for(int i = 0; i < path.size(); ++i) cnt *= path[i].se + 1; if(cnt == respow) resval = min(resval, mul); else if(cnt > respow) respow = cnt, resval = mul; return; } for(int i = 0; i < 10; ++i) if(path.empty() || arr[i] > path.back().fi) for(long long j = 1, p = arr[i] ; p * mul <= N && (path.empty() || path.back().se >= j); ++j, p *= arr[i]) path.push_back(mp(arr[i], j)), dfs(path, p * mul), path.pop_back(); } int main(){ cin >> N; vector<pii> vec; dfs(vec, 1), cout << resval << endl; return 0; }