题意:
做题时参考了http://hi.baidu.com/shuxk/item/c2b981436bfe7adac0a59213
求[1,n]中约数最多的数n<10^9
对于一个大于1正整数n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
则n的正约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1) .
那么对于这题,可以用质数连乘解决
取15个质数
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47
用它们任意连乘
有
2^a0*3^a1*......47^a14
这样的组合的约数的个数为
(a0+1)*(a1+1)*(a2+1).....(a14+1)
不断枚举这样的组合,当他大于n的时候停止
这样枚举的次数最多为10^9以内的合数的个数,至于质数,一定有2比它更优,无需考虑
这样虽然减少了很多情况,但是还是会超时
发现对于
12=2^2*3
18=3^2*2
由于约数个数相同,但是12<18,在枚举的时候加限制条件,取当前素数的个数一定小于前一个素数的个数
这样18就不会被枚举到,就减少了很多情况
具体在代码中讲
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; long long ans; long long ansnum;//约数个数 long long n; long long prime[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; //取20个质数 //2^a1 * 3^a2 * 5^a3 * 7^a4 void dfs(long long m,long long pi,long long m_num,long long pre)//m为当前的数,pi为当前枚举的素数,m_num为m的约数的个数,pre为之前的素数的个数 { if(m_num>ansnum)//更新最终结果 { ans=m; ansnum=m_num; } if(m_num==ansnum&&ans>m)//更新最终结果 { ans=m; } for(long long l=1;l<=pre;)//m*(prime[pi]^l),这里m不断乘以当前枚举的素数, { m*=prime[pi]; if(m>n) { break; } l++;//计算当前素数被乘了多少次 dfs(m,pi+1,m_num*l,l-1);//此时m的素数的个数为m_num*l } } int main() { long long total; cin>>total; while(total--) { ans=1;//最后结果的数 ansnum=1;//最后的结果的约数的个数 scanf("%lld",&n);//n的输入 //质数连乘开始 dfs(1,0,1,LONG_MAX);//初始时从1开始连乘,从第一个素数2开始, printf("%lld %lld\n",ans,ansnum); } return 0; }