zoukankan      html  css  js  c++  java
  • 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 <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #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), '', 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)<<"]"<<endl
    #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define du2(a,b) scanf("%d %d",&(a),&(b))
    #define du1(a) scanf("%d",&(a));
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
    void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    
    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 <int> 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<ll> 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
    ", ans );
        }
        return 0;
    }
    inline void getInt(int *p)
    {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        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';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    java 线程的终止与线程中断
    java 线程协作 wait(等待)与 notiy(通知)
    java 线程协作 yield()
    java 线程协作 join()
    python学习 文件操作
    linux 学习 常用命令
    linux 学习 设置固定网Ip
    web 安全
    MySQL数据物理备份之tar打包备份
    MySQL数据物理备份之lvm快照
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11617911.html
Copyright © 2011-2022 走看看