Let's denote as L(x, p) an infinite sequence of integers y such that gcd(p, y) = 1 and y > x (where gcd is the greatest common divisor of two integer numbers), sorted in ascending order. The elements of L(x, p) are 1-indexed; for example, 9, 13 and 15 are the first, the second and the third elements of L(7, 22), respectively.
You have to process t queries. Each query is denoted by three integers x, p and k, and the answer to this query is k-th element of L(x, p).
The first line contains one integer t (1 ≤ t ≤ 30000) — the number of queries to process.
Then t lines follow. i-th line contains three integers x, p and k for i-th query (1 ≤ x, p, k ≤ 106).
Print t integers, where i-th integer is the answer to i-th query.
3 7 22 1 7 22 2 7 22 3
9 13 15
5 42 42 42 43 43 43 44 44 44 45 45 45 46 46 46
187 87 139 128 141
题意:找出第k个大于x且与p互质的数
解题思路:二分+容斥验证
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
vector<int>g[1000009];
int x, p, k;
void init()
{
for (int i = 2; i <= 1000000; i++)
{
if (!g[i].size())
for (int j = i; j <= 1000000; j += i)
g[j].push_back(i);
}
}
int calc(int x)
{
int Size = g[p].size();
int ans = 0;
for (int i = 1; i<(1 << Size); i++)
{
int s = 1, cnt = 0;
for (int j = 0; j < Size; j++)
if ((i >> j) & 1) s *= g[p][j], cnt++;
if (cnt & 1) ans += x / s;
else ans -= x / s;
}
return x - ans;
}
int main()
{
init();
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d %d %d", &x, &p, &k);
int tmp = calc(x);
int l = x, r = INF, ans = x + 1;
while (l <= r)
{
int mid = (l + r) / 2;
if (calc(mid) - tmp >= k) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%d\n", ans);
}
return 0;
}