题目大意:给定一个正整数n,让你求出[1,n]内质因数个数最多的数,且该数越小越好。比如8以内,6和8都有4个因数,但6更优。
范围:n<=2*10^9
做法:dfs
拿到这种题目的时候,看到数论的东西(好吧其实这不算=w=)第一反应就是要推些什么东西出来。我们知道一个数的质因数个数是由他的质因子决定的。一个数必然能够拆分成以下的样子:n=(a1^b1)*(a2^b2)*(a3^b3)...*(ai^bi)。其中a数组表示不同的质数,b数组表示该质数在n中的数量。不难发现,n的因子个数为1*(b1+1)*(b2+1)*(b3+1)...(bi+1)。那么我们还能发现一个性质,就是当a数组中的数依次递增时,即a1<a2<a3...时,b1>=b2>=b3...。为什么呢?很显然当两个质数的次方数不同时,我们让小的质数拥有更多的次方数,这样他们的因子数量的大小不变,但是他们总的积却更小
有了这两个性质我们就可以开始搜索了。我们发现2*10^9<2*3*5*7*11*13*19*23*29,这说明我们最多只需要把a数组枚举到9就可以了。
program bzoj1053;
var
i,j,k,l,m,n:longint;
f:array[1..10] of longint;
max1,max2:longint;
procedure dfs(ans,num,sum,lnum:int64);//num表示当前枚举到第几个质数,sum表示当前所有质数的乘积,lnum表示上一个质数有多少个,ans表示当前有几个因子。
var
i:longint;
begin
if ans>max1 then begin max1:=ans; max2:=sum; end;
if (ans=max1)and(max2>sum) then max2:=sum;
for i:=1 to lnum do
begin
if sum*f[num]>n then break;//如果当前数的乘积已经超过了n那么就退出
sum:=sum*f[num];
dfs(ans*(lnum+1),num+1,sum,i);
end;
end;
begin
f[1]:=2; f[2]:=3; f[3]:=5; f[4]:=7; f[5]:=11;
f[6]:=13; f[7]:=17; f[8]:=19; f[9]:=23; f[10]:=29;
readln(n);
max1:=0;
dfs(1,1,1,1000);
writeln(max2);
end.