对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。
所以,n以内的反质数即为不超过n的约数个数最多的数。
怎样计算约数个数?
约数个数定理:
对于一个大于1正整数n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
则n的正约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1) .
其中a1、a2、a3…ak是p1、p2、p3,…pk的指数。
所以,只需枚举一个数的所有质因数就行。
最多用到的 不同的 质因数 有多少呢?
∵2*3*5*7*11*13*17*19*23*29>2000000000
∴最多只用用到这么多不同的质因数。
搜索即可。
加两个剪枝:
①从小到大枚举质因数,不要让 顺序不同的 算作不同的方案。
②小的因数的指数必然大于大的因数的指数,
∵<1>约数个数相同时,小的数更优。
<2>大的数与小的数有相同的因数个数时,根据定义,大的数压根不是反质数了。
Code:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int prime[]={0,2,3,5,7,11,13,17,19,23,29}; 5 int n,Time[11],sum; 6 long long ans; 7 int Calc() 8 { 9 int res=1; 10 for(int i=1;i<=10;i++) 11 res*=(Time[i]+1); 12 return res; 13 } 14 void dfs(long long now,int last) 15 { 16 if(now>n) 17 return; 18 int tmp=Calc(); 19 if(sum<tmp||(sum==tmp&&now<ans)){sum=tmp;ans=now;} 20 for(int i=1;i<=10;i++) 21 if(Time[i]<Time[i-1]&&i>=last) 22 { 23 Time[i]++; 24 dfs(now*prime[i],i); 25 Time[i]--; 26 } 27 } 28 int main() 29 { 30 scanf("%d",&n); 31 Time[0]=2147483647; 32 dfs(1,0); 33 cout<<ans<<endl; 34 return 0; 35 }