样例输入
3 10 100 1000
样例输出
6 60 840
题解:
比如24= 23x 3,它的因数个数有(3 + 1)*(1 +1)=8个。
本题我们只要枚举每个质数的次数即可,用DFS来寻找答案。前15个质数之积已经大于1016,所以我们枚举这15个质数就足够了。
注意第i个质数的次数一定大于第i + 1个质数的次数。因为我们是求最小的那个因数最多的数,如果大质数的次数大于小质数的次数,那交换双方次数,因数个数不会变,但是数会减小。
利用这一点,可以把每次枚举的范围缩小。还有一些剪枝, 比如当前数大于n,就不用往后考虑了。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int mod=1e9+7; 16 const double PI = acos(-1); 17 const double eps =1e-8; 18 #define Bug cout<<"---------------------"<<endl 19 const int maxn=1e5+10; 20 using namespace std; 21 const int prime[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; 22 23 LL n; 24 int ans_t;//答案的因子个数 25 LL ans;//答案 26 27 void DFS(int step,int lim,int num,LL sum)//step表示第几个质数,lim表示该质数最高次幂,num表示因子个数,sum表示总和 28 { 29 if(num>ans_t)//找因子个数最大的答案 30 { 31 ans_t=num; 32 ans=sum; 33 } 34 else if(ans_t==num&&sum<ans)//找数字最小的答案 35 ans=sum; 36 if(step>=15) return;//递归出口 37 for(int i=0;i<=lim;i++) 38 { 39 if(i!=0) sum*=prime[step]; 40 if(sum>n) break; 41 DFS(step+1,i,num*(i+1),sum); 42 } 43 } 44 45 int main() 46 { 47 #ifdef DEBUG 48 freopen("sample.txt","r",stdin); 49 #endif 50 ios_base::sync_with_stdio(false); 51 cin.tie(NULL); 52 53 int T; 54 scanf("%d",&T); 55 while(T--) 56 { 57 scanf("%lld",&n); 58 ans_t=0; 59 DFS(0,60,1,1); 60 printf("%lld ",ans); 61 } 62 63 return 0; 64 }
-