首页 > 代码库 > [BZOJ 1053] [HAOI 2007] 反素数ant
[BZOJ 1053] [HAOI 2007] 反素数ant
题目链接:BZOJ 1053
想一想就会发现,题目让求的 1 到 n 中最大的反素数,其实就是 1 到 n 中因数个数最多的数。(当有多于一个的数的因数个数都为最大值时,取最小的一个)
考虑:对于一个整数 n ,如何求 n 的因数的个数?
将 n 分解质因数,n = p1^a1 * p2^a2 * p2^a3 * ...... * px^ax 。(其中 pi 为质因数, ai 为质因数的指数)
那么 n 的因数的个数为 :Π (ai+1) (使用组合数学的知识很容易看出)
那么我们想要找到 1 到 n 的数中因数最多的一个,我们可以使用质数相乘,直接搜索。
注意最后的答案 Ans = p1^a1 * p2^a2 * ...... * px^ax ,满足当 p1 < p2 < p3 ... < px 时,a1 <= a2 <= a3 ... <= ax 。
因为对于某两个素数 p1, p2 (p1 < p2) ,若 a2 > a1,那么交换 a1, a2 之后,因数的个数并没有改变,相乘得到的数字却减小了,因此更优。
另外重要的一点是,我们只会用到前 10 个素数,因为前 10 个素数相乘就已经超过 n 的最大范围,使用更大的素数是没有意义的,不会更优。
代码如下:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int INF = 0x3fffffff;const int Prime[15] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29};typedef long long LL;LL n, Ans, Cnt;void DFS(LL Num, LL MaxP, int Now, int NowCnt) { if (NowCnt > Cnt || (NowCnt == Cnt && Num < Ans)) { Ans = Num; Cnt = NowCnt; } if (Now > 10) return; LL NowNum = Num; for (int i = 1; i <= MaxP; i++) { NowNum *= (LL)Prime[Now]; if (NowNum > n) return; DFS(NowNum, i, Now + 1, NowCnt * (i + 1)); }}int main() { scanf("%lld", &n); Ans = 1; Cnt = 1; DFS(1, INF, 1, 1); printf("%lld\n", Ans); return 0;}
[BZOJ 1053] [HAOI 2007] 反素数ant
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。