【BZOJ 1053】 [HAOI2007]反素数ant
1053: [HAOI2007]反素数ant
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1991 Solved: 1118
[Submit][Status][Discuss]
Description
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?
Input
一个数N(1<=N<=2,000,000,000)。
Output
不超过N的最大的反质数。
Sample Input
1000
Sample Output
840
HINT
呵呵,刚看到数据范围的时候我也是惊呆了。
但是到最后竟然是一道搜索题。
如果有点组合数学知识的人都知道,如果知道了一个数的素数分解式,那么就可以把每一个素数幂的指数加上1然后全部乘起来。这个我不多说了,想一想都会知道。
根据观察,我们得出一个结论:假如因数的数量相同的情况下,肯定数越小越小好。
也就是说,我们只需使用前几个素数就行了(动动脑筋~~~)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int fact[20]; int len; long long n, last, ans; bool is_prime(int m) { for (int i = 2; i * i <= m; ++i) if (m % i == 0) return false; return true; } void init() /* 把在范围内的素数选出来 */ { fact[len = 0] = 1; long long sum = 1; for (int i = 2;; ++i) if (is_prime(i)) { if (sum * i > n) return; fact[len++] = i; sum *= i; } } void dfs(int s, long long sum, long long f) { if (last < f) { ans = sum; last = f; } /* 如果因数比目前的答案多就更新 */ if (last == f) ans = min(ans, sum); /* 相等的情况下肯定是越小越好 */ if (s == len) return; long long nowp = 1; for (int i = 1;;++i) { dfs(s + 1, sum * nowp, f * i); if (sum * nowp * fact[s] > n) return; nowp *= fact[s]; } } int main() { cin >> n; init(); ans = 0; last = 0; dfs(0, 1, 1); cout << ans << endl; return 0; }