[luogu p1221][codevs 1032]最多因子数

题目描述

数学家们喜欢各种类型的有奇怪特性的数。例如,他们认为945是一个有趣的数,因为它是第一个所有约数之和大于本身的奇数。

为了帮助他们寻找有趣的数,你将写一个程序扫描一定范围内的数,并确定在此范围内约数个数最多的那个数。不幸的是,这个数和给定的范围的都比较大,用简单的方法寻找可能需要较多的运行时间。所以请确定你的算法能在几秒内完成最大范围内的扫描。

输入输出格式

输入格式:

只有一行,给出扫描的范围,由下界L和上界U确定。满足2≤L≤U≤1000000000。

输出格式:

对于给定的范围,输出该范围内约数个数D最多的数P。若有多个,则输出最小的那个。请输出“Between L and U,P has a maximum of D divisors.”,其中L,U,P和D的含义同前面所述。

输入输出样例        别点复制,没用的:)

输入样例#1:  复制
1000 2000
输出样例#1:  复制
Between 1000 and 2000, 1680 has a maximum of 40 divisors.

传送门

这题的思路嘛。。。。

其实就是爆搜。

首先我们要知道,一个数X可以被分解为X=2m13m25m3...nmk

相信聪明的大家都能理解(注:n为质数)

当分解完后,X的个数为(m1+1)(m2+1)(m3+1)...(mk+1)

扫描二维码关注公众号,回复: 2166107 查看本文章

根据乘法原理,选1个,2个……m1个,为啥是m1+1?还可以不选haha

我们只需把质数预处理出来,然后暴力填m1,m2,m3,……,mk即可

加上一点剪枝

代码:(卡常大法好)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 10005;
const int INF = 1000000007;
ll _[N],prime[N],size,ansp=INF,ansd,anss[N],l,r;
//p 素数 2 3 5 7 (第几个质因子)
//all已经搜索到的k的因子的乘积
//last上一个的p的指数 
inline void dfs(int p,ll all,ll last){
    if(l<=all&&all<=r){//满足要求
        int o=1;
        for(register int i=1;i<p;i++){//算出约数个数
            o=o*(anss[i]+1);
        }
        if(o>ansd||(o==ansd&&all<ansp)){//最小
            ansd=o;
            ansp=all;
        }
    }
    if(all>ansp) return;//最优性剪枝
    ll lin[100]={0};
    lin[0]=1;
    for(register int i=1;i<=last;i++) lin[i]=lin[i-1]*prime[p];//预处理
    for(register int i=last;i>=1;i--){//从后往前,更高效
        anss[p]=i;	
        dfs(p+1,all*lin[i],i);
    }
}
void bao_li_chu_qi_ji(){//只可会意,不可言传
    for(int i=l;i<=r;i++){
        int ret=0;
        for(int j=1;j*j<=i;j++){
            if(i%j==0) ret+=2;
            if(j*j==i) ret--;
        }
        if(ret>ansd){
            ansp=i;
            ansd=ret;
        }
    }
}
int main(){
    for(register int i=2;i<=sqrt(N);i++){
        for(register int j=2;j*i<N;j++){
            _[i*j]=1;
        }
    }
    for(register int i=2;i<=N;i++){
        if(!_[i]) prime[++size]=i;
    }
    scanf("%lld%lld",&l,&r);
    ll w=log(r);
    if(r-l<5000) bao_li_chu_qi_ji();//只可会意,不可言传
    else dfs(1,1,w);
    printf("Between %lld and %lld, %lld has a maximum of %lld divisors.\n",l,r,ansp,ansd);
    return 0;
}

跑得还挺快的。。

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/81052458