反素数ant

问题 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;
}


 

猜你喜欢

转载自blog.csdn.net/renzijing/article/details/81072045