题目链接: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;
}