hdu6641TDL(19年杭电第六场多校赛第8题)

TDL
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0

Problem Description
For a positive integer n, let’s denote function f(n,m) as the m-th smallest integer x that x>n and gcd(x,n)=1. For example, f(5,1)=6 and f(5,5)=11.

You are given the value of m and (f(n,m)−n)⊕n, where ``⊕’’ denotes the bitwise XOR operation. Please write a program to find the smallest positive integer n that (f(n,m)−n)⊕n=k, or determine it is impossible.

Input
The first line of the input contains an integer T(1≤T≤10), denoting the number of test cases.

In each test case, there are two integers k,m(1≤k≤1018,1≤m≤100).

Output
For each test case, print a single line containing an integer, denoting the smallest n. If there is no solution, output ``-1’’ instead.

Sample Input
2
3 5
6 100

Sample Output
5
-1
题意: 给出f(n,m),即为大于n的第m个与n互质的数,给出k和m,找出最小的n使其满足(f(n,m)-n) ^ n = k。
思路: 要使其异或结果为k,则n与另一个数的二进制位数一定是和k的二进制位数相同,又m小于100,打表可发现第m个与n互质的数的差值不超过1000,所以枚举k的左边界和右边界区域即可,如果k小于等于1000,其左边界从1开始,否则从k-1000开始,右边界为k+1000。详情看代码。

#include 
using namespace std;
typedef long long ll;
ll f(ll x, ll m) { // 找出从x+1开始第m个与x的最大公约数为1的数 
	ll k = 0, ans;
	for (ll i = x + 1; ; i++) {
		if (__gcd(i, x) == 1) {
			k++;
			ans = i;
		}
		if (k == m) {
			return ans;
		}
	}
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		ll k, m;
		scanf("%lld%lld", &k, &m);
		if (k == m) { 
			// k和m相同时直接输出-1,因为此时的n的二进制位数一定大于k的位数 
			printf("-1\n");
			continue;
		}
		ll tt;
		if (k < 1001) tt = 1; // 确定解的左边界 
		else tt = k - 1000;
		ll flag = 0;
		for (ll i = tt; i < k + 1000; i++) {
			if ((f(i, m) - i) == (k ^ i)) {
				flag = i;
				break;
			}
		}
		if (!flag) {
			printf("-1\n");
		} else {
			printf("%lld\n", flag);
		}
	}
	return 0;
}

你可能感兴趣的:(hduoj)