求n以内的因子最多的数

51nod 1060 求n以内的因子最多的数(不止一个则取最小)
把一个数的约数个数定义为该数的复杂程度,给出一个n,求1-n中复杂程度最高的那个数。 
例如:12的约数为:1 2 3 4 6 12,共6个数,所以12的复杂程度是6。如果有多个数复杂度相等,输出最小的
#include 
using namespace std;
typedef long long LL;
const int MAXP = 16;//最大深度,下面的质数表由2乘到53就超过了10^18
const int prime[MAXP] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
LL n,res,ans;
void dfs(LL cur, LL num, int key, LL pre){//当前值/当前约数数量/当前深度/上一个数
    if (key >= MAXP)return ;//当前深度大于最大深度就不用计算了
    else{
        if(num>ans){res=cur;ans=num;}//当前约数数量大过全局变量ANS,就更新RES与ANS
        else if (num == ans)res = min(cur, res);//如果约数数量相同,则取较小的数
        for (LL  i = 1; i <= pre; i++){//由1开始遍历到上一个数
            if (cur <= n / prime[key]){//cur*prime[key]<=n//当前值乘上当前深度质数未超N
                cur *= prime[key];//未够N,那CUR就可以乘上当前深度的质数然后递归
                dfs(cur, num * (i + 1), key + 1, i);
            }
            //CUR是当前的数的值,每一轮递归都乘上当前深度的质数
            //因为当前深度的质数乘了I次,所以复杂度翻了I+1倍
            //下一轮要乘的深度值加1
            //i就是下一轮的PRE,控制着还可以继续乘多少个数
            else break;//当前值乘上当前深度的质数超N就可以结束
        }
    }
}
void solve(){
    res = 1;//初始化那个数是1
    ans = 1;//1的复杂度是1,只要大过1复杂度至少是2了
    dfs(1, 1, 0, 15);//开始深搜
    cout << res << ' ' << ans << endl;//输出那个数及其复杂度
}
int main(){
    int T;cin >> T;//T个数据
    while (T--){
        cin >> n;//求N以内最复杂的数
        solve();
    }
    return 0;
}。
Input示例 
5 
1 
10 
100 
1000 
10000 
Output示例 
1 1 
6 4 
60 12 
840 32 
7560 64
首先我们需要知道一个求因子个数的定理:
假设正整数n质因子分解为:n = p1^n1 * p2^n2 * p3^n3 * ... * pk^nk
其中pi表示质因子,ni表示该质因子的数量
则有n的因子个数为:D = (n1+1)*(n2+1)*(n3+1)* ... * (nk+1)
由此得到本题的一个基本解题思路:
枚举质因子数量,在使得n不超过N的情况下,使得D尽可能大
为了要D尽可能大,需要ni尽可能大,所以pi要尽可能小。
因此我们从最小的质数2开始枚举每一个质因子的数量ni,来计算n。
对最小解来一定有:若pi和pj都属于n的质因子,且pi < pj,则一定有ni≥nj,证明:
假设存在nj > ni,则有:。n' = n / pj^(nj-ni) * pi(nj-ni)
n’的质因子个数和n相比,只是交换了ni和nj的值,D的值不会发生变化。
而由于pj > pi,因此 n’ < n,所以 n 不是最小解。
这就是为什么每次要传个i作为下一轮的PRE

最后一个问题:一开始传入去的PRE是15的合理性,为什么2不能超15次方?

 

你可能感兴趣的:(ACM笔记-5代数)