问题 B: 反素数ant
时间限制: 1 Sec 内存限制: 128 MB
提交: 9 解决: 7
[提交] [状态] [讨论版] [命题人:admin]
题目描述
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。现在给定一个数N,你能求出不超过N的最大的反质数么?
输入
一个数N(1<=N<=2,000,000,000)。
输出
不超过N的最大的反素数。
样例输入
1000
样例输出
840
首先,需要知道几个数论的结论(省略了证明)
1.每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。即n = P1^a1 * P2^a2 * …………* (P1 < P2 < ……Pn) (算数基本定理)
2.一个数的因子个数=(a1+1)*(a2+1)*……*(an+1)
3.较小的指数个数一定小于较大的,即a1>=a2>=……>=an
4.一个2000000000以内的数字不会有超过12个素因子
然后进行深搜,加一个剪枝
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxx=1e5+100;
const int INF=1e9;
const int MOD=1e9+7;
typedef long long ll;
int prime[20]={2,3,5,7,11,13,17,19,23,29,31,37};
ll n;
ll ans=1,num=1; //ans为最大数,num为最大数的约数个数
void dfs(int dep,ll now,ll cnt,int limit) // dep为第几个素数,now为当前数,cnt为当前约数个数,limit为最多搜索次数
{
if(now>n) return ;
if(cnt>num){ //约数个数大于num
ans=now;
num=cnt;
}
if(cnt==num && now<ans) //约数个数相等但当前数小于ans
ans=now;
if(dep>11) return ;
ll k=now;
for(int i=1; i<=limit; i++){
if(k*prime[dep]>n) break;
k=k*prime[dep];
dfs(dep+1,k,cnt*(i+1),i);
}
}
int main()
{
cin>>n;
dfs(0,1,1,30);
cout<<ans<<endl;
return 0;
}