您的位置:首页 > 其它

HDU 4542 小明系列故事——未知剩余系

2015-06-26 11:07 239 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4542

参考了ACdreamer的博客:http://blog.csdn.net/ACdreamers/article/details/25049767

首先对于本题

(1)Type = 0即求解约数个数为K结果是一定存在,只不过存在超出范围和不超出范围两种情况,这个与反素数有关,采用dfs+剪枝的搜索

(2)Type = 1即求解约数个数为N-K的最小的数,我们很容易知道对于一个数N,它的约数的个数<=2*sqrt(N),因此对于K<=50000,我们完全可以预处理出前60000的约数个数,来求解该问题,对于>60000,N-2*sqrt(N) > K,我们便不需要考虑。

因此我们很容易写出下面的程序:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
const int maxn = 60010;
const ll inf = (1LL<<62)+1;
int p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};

bool is_prime[maxn];
int  prime[maxn];
int  val[maxn];
int  len;
int  K;
ll   ans;

void init() {
    int i, j;
    len = 0;
    memset(is_prime, true, sizeof(is_prime));
    for(i = 4; i < maxn; i += 2) is_prime[i] = false;
    prime[len++] = 2;
    for(i = 3; i * i <= maxn; i += 2) {
        if(is_prime[i]) {
            prime[len++] = i;
            for(j = i * i; j < maxn; j += i) {
                is_prime[j] = false;
            }
        }
    }
    for( ; i < maxn; i += 2) {
        if(is_prime[i]) {
            prime[len++] = i;
        }
    }
}

int get_factor(int x) {
    int ans = 1;
    for(int i = 0; i < len && prime[i] * prime[i] <= x; ++i) {
        if(x % prime[i] == 0) {
            int cnt = 0;
            while(x % prime[i] == 0) {
                x /= prime[i];
                cnt++;
            }
            ans *= (cnt + 1);
        }
    }
    if(x > 1) ans *= 2;
    return ans;
}

void solve() {
    memset(val, 0x3f3f3f3f, sizeof(val));
    for(int i = 1; i < maxn; ++i) {
        int cnt = get_factor(i);
        val[i-cnt] = min(val[i-cnt], i);
    }
}

void dfs(int pos, int lim, ll cur, ll num) {
    if(pos > 15) return ;
    if(num > K) return ;
    if(num == K) {
        ans = min(ans, cur);
        return ;
    }
    for(int i = 1; i <= lim; ++i) {
        if(ans/p[pos] < cur || num*(i+1) > K) break;
        if(K%(num*(i+1)) == 0) {
            dfs(pos + 1, i, cur * p[pos], num*(i+1));
        }
        cur *= p[pos];
    }
    return ;
}

int main() {

    //freopen("aa.in", "r", stdin);

    init();
    solve();
    int T, type;
    int kcase = 0;
    scanf("%d", &T);
    while(T--) {
        kcase++;
        scanf("%d %d", &type, &K);
        printf("Case %d: ", kcase);
        if(type == 1) {
            if(val[K] >= 0x3f3f3f3f) {
                printf("Illegal\n");
            } else {
                printf("%d\n", val[K]);
            }
        } else {
            ans = inf;
            dfs(0, 62, 1, 1);
            if(ans >= inf) {
                printf("INF\n");
            } else {
                printf("%I64d\n", ans);
            }
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: