题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1053
这个题很有意思,虽然代码很短,但是思路非常巧妙。
首先这个题问不超过N的最大的x,使得任何比x小的数的约数个数都比x的约数个数少。其实说到底就是求[1,n]中约数个数最多的数,如果有多个这样的数,取最小的(因为题目要求任何比x小的数的约数个数都必须小于x的约数个数,不能取等)。另外做这题之前还要掌握约数个数公式:若把x表示成多个质因数的乘积,x=p1^a1*p2^a2*...pn^an,p1,p2...pn是质数,那么x的约数个数=(a1+1)*(a2+1)*...(an+1)。我们可以直接DFS暴搜找答案,枚举每一个质因数的幂,然后根据已经乘积得出的数的约数个数,不断更新答案。另外此题有个小技巧需要注意:枚举的质因数只要是从小到大前10个质数就可以了,因为从小到大前十个以上的质数的乘积已经超出了n的最大范围。而且枚举第i个质因数的幂时,第i个质因数的幂大小不会超过第i-1个质因数的幂。(因为差不多大小的数字,大的质因数的指数比小的质因数的指数大的数字绝对没有小的质因数的指数比大的质因数指数大的数字的约数个数多,根据贪心思想,大的质因数会占用更大的积,不如小的质因数来得划算)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long int LL;
int primes[]={0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; //质数打表
LL n,ans,cnt; //cnt=约数个数最大值,ans=约数个数取最大值时的最小的数字
void DFS(LL num,LL maxP,int now,int nowcnt) //num=当前乘积得到的数,maxp=下一个质数最大的幂,now=当前状态下使用的质数下标,nowcnt=当前数约数个数
{
if(nowcnt>cnt||nowcnt==cnt&&num<ans)
{
cnt=nowcnt;
ans=num;
}
if(now>10) return; //取的质数个数太多了,已经超出了n的范围,不必继续搜索了
LL nownum=num;
for(int i=1;i<=maxP;i++) //枚举下一个质因数的幂
{
nownum*=(LL)primes[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;
}