Educational Codeforces Round 37 G. List Of Integers (二分,容斥定律,数论)

G. List Of Integers

time limit per test

5 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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).

Input

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).

Output

Print t integers, where i-th integer is the answer to i-th query.

Examples

input

Copy

37 22 17 22 27 22 3

output

Copy

91315

input

Copy

542 42 4243 43 4344 44 4445 45 4546 46 46

output

Copy

18787139128141

题目链接:

https://codeforces.com/contest/920/problem/G

题意:

有t组询问,对于每一组询问,

给你三个整数x,p,k

问有在大于x的整数中,与p互质的第k小的数y是哪个?

思路:

对于每一组询问我们在区间\([x+1,1e9]\) 这个区间内,二分答案y

同时容斥定律可以求得区间\([l,r]\) 中与一个数num互质的数个数。——知识点[1]

那么我们可以求区间\([x+1,y]\)中与p互质的数个数与k比较,然后进行转移区间即可。

先筛出\(1e6\) 内的所有质数,然后\(log(p)\) 的时间复杂度去唯一分解询问中的p,然后二进制枚举+容斥定律辅助二分即可。

不会的话,建议先学一下知识点1,再来解决本题。

code:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i
#define pll pair
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<>= 1;} return ans;}
void Pv(const vector &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}

inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
// const int maxn = 1e7 + 50;
bool noprime[maxn + 50];
vector  p;
int getPrime()
{
    // 华丽的初始化
    memset(noprime, false, sizeof(noprime));
    p.clear();

    int m = (int)sqrt(maxn + 0.5);
    // 优化的埃筛
    for (int i = 2; i <= m; i++) {
        if (!noprime[i]) {
            for (int j = i * i; j <= maxn; j += i) {
                noprime[j] = true;
            }
        }
    }
    // 把素数加到vector里
    for (int i = 2; i <= maxn; i++) {
        if (!noprime[i]) {
            p.push_back(i);
        }
    }
    //返回vector的大小
    return p.size();

}
std::vector v;
void breakdown(ll n, ll len)
{
    int pos = 0;
    for (int i = 0; 1ll * p[i]*p[i] <= n && i < len; i++) {
        if ( n % p[i] == 0) {
            v.push_back(p[i]);
            while (n % p[i] == 0) {
                n /= p[i];
            }
        }
    }
    if ( n > 1) {
        v.push_back(n);
    }

}
int x, pw, k;
int len ;
ll solve(ll l, ll r)
{
    int maxstate = (1 << len) - 1;
    ll ans = 0ll;
    l--;
    for (int i = 0; i <= maxstate; ++i) {
        int num = 0;
        ll p = 1ll;
        for (int j = 0; j < len; ++j) {
            if (i & (1 << j)) {
                num++;
                p *= v[j];
            }
        }
        ans += (r / p - l / p) * ((num & 1) ? -1ll : 1ll);
    }
    return ans;
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int n;
    int w = getPrime();
    du1(n);
    while (n--) {
        du3(x, pw, k);
        v.clear();
        breakdown(pw, w);
        len = sz(v);
        ll l = x + 1ll;
        ll r = 1e8;
        ll mid;
        ll ans;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (solve(x + 1ll, mid) >= k) {
                ans = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        printf("%lld\n", ans );
    }
    return 0;
}
inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}



你可能感兴趣的:(Educational Codeforces Round 37 G. List Of Integers (二分,容斥定律,数论))