Codeforces 920G-List Of Integers

44 篇文章 0 订阅
5 篇文章 0 订阅

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, 913 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 xp 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 xp 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
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

题意:找出第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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值