1088 – 【SCOI2003】Antiprime数
Description
  如果一个自然数n(n>=1),满足所有小于n的自然数(>=1)的约数个数都小于n的约数个数,则n是一个Antiprime数。譬如:1, 2, 4, 6, 12, 24。
  任务:编一个程序:
    1、从ANT.IN中读入自然数n。
    2、计算不大于n的最大Antiprime数。
    3、将结果输出到ANT.OUT中。
Input
  输入只有一个整数,n(1 <= n <= 2 000 000 000)。
Output
  输出只包含一个整数,即不大于n的最大Antiprime数。
Sample Input
1000
Sample Output
840
Source
xinyue


【分析】
首先问题可以转化成求n以内约数最多的数,约数相同则取小的。
一个数x=a1^p1* a2^p2* …* an^pn(a是质数)的约数个数为(a1+1)* (a2+1)* …* (an+1)。
考虑到2* 3* 5* 7* 11* 13* 17* 19>2e9,可以将这些素数打表,之后搜索每个素数的次数即可。
显然可以得到这个剪枝:从2向后,每个素数的指数单调不增。从而也有一个推论,就是不能跳着取素数。这样运行速度就很快了。


【代码】

//巴蜀 1008 Antiprim数 
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=9;
ll n,ans=1e10,yue;
int a[15]={0,2,3,5,7,11,13,17,19,23};
inline void dfs(int k,ll now,ll num) //now:现在有多大,num:约数个数
{
int i,j;
if(k>9)
{
if(num>yue)
ans=now,yue=num;
if(num==yue)
ans=min(ans,now);
return;
}
dfs(k+1,now,num); //不选a[k]
fo(i,1,100)
{
if(now*a[k]>n) break;
now*=a[k];
dfs(k+1,now,num*(i+1));
}
}
int main()
{
int i,j;
scanf("%lld",&n);
dfs(1,1,1);
printf("%lld\n",ans);
return 0;
}