【BZOJ 1053】 [HAOI2007]反素数ant

1053: [HAOI2007]反素数ant

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1991  Solved: 1118
[Submit][Status][Discuss]

Description

 

对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?

Input

一个数N(1<=N<=2,000,000,000)。

Output

不超过N的最大的反质数。

Sample Input

1000

Sample Output

840

HINT

 

呵呵,刚看到数据范围的时候我也是惊呆了。

但是到最后竟然是一道搜索题。

如果有点组合数学知识的人都知道,如果知道了一个数的素数分解式,那么就可以把每一个素数幂的指数加上1然后全部乘起来。这个我不多说了,想一想都会知道。

根据观察,我们得出一个结论:假如因数的数量相同的情况下,肯定数越小越小好。

也就是说,我们只需使用前几个素数就行了(动动脑筋~~~)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

int fact[20];
int len;
long long n, last, ans;

bool is_prime(int m)
{
    for (int i = 2; i * i <= m; ++i)
        if (m % i == 0) return false;
    return true;
}

void init()    /* 把在范围内的素数选出来 */
{
    fact[len = 0] = 1;
    long long sum = 1;
    for (int i = 2;; ++i)
        if (is_prime(i))
        {
            if (sum * i > n) return;
            fact[len++] = i;
            sum *= i;
        }
}

void dfs(int s, long long sum, long long f)
{
    if (last < f) { ans = sum; last = f; }    /* 如果因数比目前的答案多就更新 */
    if (last == f) ans = min(ans, sum);    /* 相等的情况下肯定是越小越好 */
    if (s == len) return;
    long long nowp = 1;
    for (int i = 1;;++i)
    {
        dfs(s + 1, sum * nowp, f * i);
        if (sum * nowp * fact[s] > n) return;
        nowp *= fact[s];
    }
}

int main()
{
    cin >> n;
    init();
    ans = 0;
    last = 0;
    dfs(0, 1, 1);
    cout << ans << endl;
    return 0;
}

 

posted @ 2015-08-27 13:51  albertxwz  阅读(236)  评论(0编辑  收藏  举报