Codeforces 920G - List Of Integers 【容斥+二分】


G. List Of Integers

time limit per test 5seconds

memory limit per test     256megabytes

Let's denote asL(x, p) an infinitesequence of integers y such that gcd(p, y) = 1 and y > x (where gcd is the greatestcommon divisor of two integer numbers), sorted in ascending order. The elementsofL(x, p) are 1-indexed; forexample, 9,13 and 15 are the first,the second and the third elements of L(7, 22), respectively.

You have to processt queries. Eachquery is denoted by three integers x,p and k, and the answerto this query is k-th element of L(x, p).

Input

The first line contains one integert (1 ≤ t ≤ 30000) — the numberof queries to process.

Thent lines follow. i-th linecontains three integers x,p and k for i-th query (1 ≤ x, p, k ≤ 106).

Output

Printt integers, where i-th integer isthe answer to i-th query.

Examples

Input

3
7 22 1
7 22 2
7 22 3

Output

9
13
15

Input

5
42 42 42
43 43 43
44 44 44
45 45 45
46 46 46

Output

187
87
139
128
141

 


【题意】


求大于x且与p互质的第k大的数。


【思路】


对于任意的x,我们可以用快速容斥求出【1,x】中与p互质的数的个数。


那么我们先算【1,x】中与p互质的数的个数num,那么我们要输出的便是第(num+k)个与p互质的数。


由前面可知,我们利用容斥然后二分即可。


#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 200005;
const ll mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;

ll x,p,k;
vector<ll>vec;

ll cal(ll x)
{
    ll ans=0;
    int num=vec.size();
    for(int i=0;i<(1<<num);i++)
    {
        ll now=1,flag=1;
        for(int j=0;j<num;j++)
        {
            if((i>>j)&1)
            {
                now*=vec[j];
                flag*=-1;
            }
        }
        ans+=flag*(x/now);
    }
    return ans;
}

int main()
{
    rush()
    {
        scanf("%lld%lld%lld",&x,&p,&k);
        vec.clear();
        for(ll i=2;i*i<=p;i++)
        {
            if(p%i==0) vec.push_back(i);
            while(p%i==0) p/=i;
        }
        if(p>1) vec.push_back(p);
        k+=cal(x);
        ll l=1,r=1e12;
        ll ans=-1;
        while(l<=r)
        {
            ll m=(l+r)/2;
            if(cal(m)>=k)
            {
                ans=m;
                r=m-1;
            }
            else l=m+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值