题目链接:http://poj.org/problem?id=2773
题意:求第k个与m互素的数, 将m进行素因子分解, 假设为p1, p2, p3...pn可以用容斥原理求出与一个素因子不互素的数的个数, 减去与两个素因子的积不互素的数的个数, 在加上与三个。。。由于素因子的个数只有log级别所以我们可以用dfs快速得到与m不互素的数的个数,再根据这个值进行二分即可, 细节详见代码。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
const int N = 1000005;
typedef long long LL;
const LL INF = 1LL << 60;
int prime[N];
int fac[N];
bool vis[N];
int lim;
void sieve(int n) {
int m = sqrt(n + 0.5);
for (int i = 2; i <= m; i++) if (!vis[i])
for (int j = i * i; j <= n; j += i) vis[j] = 1;
}
int get_primes(int n) {
sieve(n);
int c = 0;
for (int i = 2; i <= n; i++)
if (!vis[i])
prime[c++] = i;
return c;
}
void dfs(int id, LL now, LL& res, bool flag, LL v) {
if (id == lim) return;
dfs(id + 1, now, res, flag, v);
LL key = now * fac[id];
if (flag)
res += v / key;
else
res -= v / key;
dfs(id + 1, key, res, !flag, v);
}
LL jud(LL val) {
LL res = 0;
dfs(0, 1, res, 1, val);
return val - res;
}
int main() {
int c = get_primes(N - 5);
int m, k, tar;
while (~scanf("%d%d", &m, &k)) {
if (k == 1) {
puts("1");
continue;
}
tar = m;
lim = 0;
for (int i = 0; prime[i] <= m; i++) {
while (m % prime[i] == 0) {
fac[lim++] = prime[i];
m /= prime[i];
}
}
lim = unique(fac, fac + lim) - fac;
LL L = 2, R = INF;
while (L <= R) {
LL mid = L + R >> 1;
if (jud(mid) >= k)
R = mid - 1;
else
L = mid + 1;
}
printf("%lld\n", L);
}
return 0;
}