反素数法

首先了解一点,求解一个数的因子个数。

假设p[]数组里全部是素数,那么任何一个整数,可以唯一的表示成n=p1^x1*p2^x2*p3^x3.......*pm^xm,那么因子个数便为:(x1+1)*(x2+1)*.....*(xm+1)。

 

给定一个整数n,求解1~~n范围内,因子个数最多的那个数,如果相同的话,取较小的。

这里要认识到一点,因子数最多的那个数,根据我们上面说的,可以由素数的乘积组成。那么我们枚举素数的幂,也就是上面式子上的x1,x2,x3...xm。就可以遍历到1~~n范围内的所有可能解。假设n的取值范围是10^18次方,看起来很大是吧,对于素数2来说,2^60次方就大于10^18次方了,而且我们可以发现,上面的式子中x1>=x2>=x3>=....xm。而最大的那个也最多只有60次枚举,所以说,枚举起来速度是很快的。

 

 

View Code
 1 #include<iostream>
 2 #include<string>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int prim[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
 7 __int64 n;
 8 __int64 ans; //答案
 9 int complexity; //因子个数
10 
11 void dfs(int k,int limited,__int64 now,int com) //目前在第k个素数,最多搜索limited次,now是目前的数,com是目前的因子数
12 {
13     if(now>n)
14         return;
15     if(com>complexity)
16     {
17         complexity=com;
18         ans=now;
19     }
20     if(com==complexity && now <ans)
21         ans=now;
22     if(k>15)
23         return;
24     int i;
25     __int64 m=now;
26     for(i=1;i<=limited;i++)
27     {
28         if(m*prim[k]>n)
29             break;
30         m=m*prim[k];
31         dfs(k+1,i,m,com*(i+1));
32     }
33 }
34 
35 int main()
36 {
37     while(scanf("%I64d",&n)==1)
38     {
39         complexity=0;
40         ans=0;
41         dfs(0,60,1,1);
42         printf("%I64d %d\n",ans,complexity);
43     }
44     return 0;
45 }
posted @ 2012-08-14 20:30  Accept  阅读(526)  评论(0编辑  收藏  举报