[POI2001] [HAOI2007] 反素数
题目描述
对于任何正整数 x x x,其约数的个数记作 g ( x ) g(x) g(x)。例如 g ( 1 ) = 1 g(1)=1 g(1)=1, g ( 6 ) = 4 g(6)=4 g(6)=4。
如果某个正整数 x x x 满足: ∀ 0 < i < x \forall 0 \lt i \lt x ∀0<i<x,都有 g ( x ) > g ( i ) g(x) \gt g(i) g(x)>g(i),则称 x x x 为反质数。例如,整数 1 , 2 , 4 , 6 1,2,4,6 1,2,4,6 等都是反质数。
现在给定一个数 N N N,你能求出不超过 N N N 的最大的反质数么?
输入格式
一个数 N N N。
输出格式
不超过 N N N 的最大的反质数。
样例 #1
样例输入 #1
1000
样例输出 #1
840
提示
1 ≤ N ≤ 2 × 1 0 9 1 \leq N \leq 2 \times 10^9 1≤N≤2×109
分析
首先考虑 g(x) 的求法:
设
x
=
∏
p
i
k
i
设 x = \prod p^{k_i}_i
设x=∏piki
则
g
(
x
)
=
∏
k
i
+
1
,其中
p
i
∈
P
则 g(x) =\prod k_i+1,其中p_i \in P
则g(x)=∏ki+1,其中pi∈P
比如12,可以写为
12
=
2
2
⋅
3
,
12=2^2 \cdot 3,
12=22⋅3,
g
(
12
)
=
3
∗
2
=
6
g(12)=3*2=6
g(12)=3∗2=6
证明:乘法原理
所以对于一个反素数 x,假设
p
i
p_i
pi 是单增的,那么
k
i
k_i
ki 必须不升
代码
#include<bits/stdc++.h>
using namespace std;
int p[] = {0,2,3,5,7,11,13,17,19,23,29};
int tot = 0,n;
pair<int, int> a[1000000];
void dfs(int i, int last, int pi,int k) {
a[++tot] = make_pair(pi, k);
if (i > 9) return;
else {
int pp = p[i];
for (int j = 1; j <= last; j++) {
if (1ll * pi* pp > n) break;
pi *= pp;
dfs(i + 1, j, pi, k * (j + 1));
}
}
return;
}
signed main() {
cin >> n; dfs(1, 100, 1, 1);
sort(a + 1, a + tot + 1);
int maxn = a[1].second,ans=a[1].first;
for (int i = 2; i <= tot; i++) {
if (a[i].second > maxn) {
maxn = a[i].second;
ans = a[i].first;
}
}
cout << ans;
return 0;
}
分析
只要把可能是反素数的数筛出来,在判断就可以了,怎么筛可以参考上面的分析
这里需要注意下
int maxn = a[1].second,ans=a[1].first;
for (int i = 2; i <= tot; i++) {
if (a[i].second > maxn) {
maxn = a[i].second;
ans = a[i].first;
}
}
cout << ans;
取走最大值不一定选个-1或-INF作为初始值。可以采用以上方法,在别的题目中,取-1仍存在风险,可能-1比正确答案还大