http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1562
题意:求小于等于n(1 <= n <= 1016)的约数个数最多的数。
根据反素数的定义,这个题就是让求最大的反素数。
反素数搜索的依据的两个重要的性质:
反素数的质因子是从2开始的连续的素数;
p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....
另外一个性质:对于p=2^t1*3^t2*5^t3*7^t4.....,p的因子的个数为(t1+1)*(t2+1)......*(tn+1)。
因为n最大是10^16,因此t最大可以为54,根据以上性质枚举每一个素数以及每一个素数的个数进行搜索。
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
LL n;
int prime[20] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
LL Maxcur; //当前最大的反素数
int Maxcnt;//最大反素数对应的因子个数
void get_antiprime(LL cur, int cnt, int Maxnum, int k)
{
if(cur > n)
return;
if(cnt > Maxcnt)
{
Maxcnt = cnt;
Maxcur = cur;
}
if(cnt == Maxcnt && cur < Maxcur)
{
Maxcur = cur;
}
LL tmp = cur;
//枚举第K个素数的个数
for(int i = 1; i <= Maxnum; i++)
{
tmp *= prime[k];
if(tmp > n)
return;
get_antiprime(tmp,cnt*(i+1),i,k+1);
}
}
int main()
{
while(~scanf("%lld",&n))
{
Maxcur = 1;
Maxcnt = 1;
get_antiprime(1,1,54,0);
printf("%lld\n",Maxcur);
}
return 0;
}