zoukankan      html  css  js  c++  java
  • [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
    ", Ans);
    	return 0;
    }
    

      

  • 相关阅读:
    2021广东省强网杯WriteUp
    2021 数字四川创新大赛WriteUp
    2021 陇剑杯wp
    2021 羊城杯WriteUP
    如何翻安全四大顶会的文章
    2021 祥云杯 wp
    codeql初探
    sqlmap应用
    sql注入2
    sql注入
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4160898.html
Copyright © 2011-2022 走看看