题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1562
题解:g(x)表示x的因子个数。
如果满足对于任意的0<i<x,有g(i)<g(x),则称x为反素数。
它有如下性质:
1、一个反素数的质因子一定是从2开始的连续的质数。
2、一个反素数可以唯一表示成2^a*3^b*5^c······的形式,并且a>=b>=c>=d······。
证明:(仅供参考)
先证明性质2:
因为每个整数都有唯一的因式分解,所以表示唯一。
设某个整数Y的因式分解中有t1 个2,t2个3,t3个5······
则Y的因子数为sum=(t1+1)*(t2+1)*(t3+1)······
而Y=2^t1*3^t2*5^t3······
因为要使sum最大,则需要增大t1,t2,t3······的值,而对于2的指数t1,增大的速度最大,所以a最大,其次是b,c。
有了性质2,因为a>=b>=c>=d的。所以中间不会出现0的情况。所以连续。
求n以内的数,该数的因子数最多。
就是要求n以内的最大反素数x。
证明:
在x以内,g(x)最大,在大于x小于n之间不存在因子数大于g(x)的数。
假设存在p,使g(p)>g(x),则p就是n以内的最大反素数,与x使最大反素数矛盾,顾不存在p。
n的最大值是10^16.
则最多用到14个素数来表示n。(2 3 5 7 11 13 17 19 23 29 31 37 41 43)
源代码:
#include <stdio.h>
typedef long long ll;
int prime[14]={2,3,5,7,11,13,17,19,23,29,31,37,41,43};
ll max,best;
ll n;
void getAnti_prime(ll num,int k,ll sum,int limit)
{
ll temp;
if(sum>max)
{
max=sum;
best=num;
}
if(sum==max&&best>num) best=num;
if(k>=14) return;
temp=num;
for(int i=1;i<=limit;i++)
{
if(temp*prime[k]>n)
break;
temp=temp*prime[k];
getAnti_prime(temp,k+1,sum*(i+1),i);
}
}
int main()
{
while(scanf("%lld",&n)!=EOF)
{
getAnti_prime(1,0,1,50);
printf("%lld\n",best);
}
}