bzoj1053[HAOI2007]反素数ant

来源:互联网 发布:爱丽丝疯狂回归知乎 编辑:程序博客网 时间:2024/04/25 07:00

题目大意:给定一个正整数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.

0 0
原创粉丝点击