gcd是求最大公约数
若想消除位异或符号,可等号两边同时异或,如:
a ^ b = c —> a ^ b ^ b = c ^ b —> a = c ^ b
本题k的范围(1,10^18),若将k异或n,二进制的前面部分不改变,变化的是n的二进制的位数,因为f(n, m) − n 不会超过第m个与n互质的质数,m最大为100,所以可以确定上限
只要确定n的上限,直接暴力就可以AC了
#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
#define ll long long
ll gcd(ll a,ll b) {
while(b^=a^=b^=a%=b);
return a;
}
ll f(ll n, ll m) {
ll i = 1,k = 0;
while(i<=m*100) {
if(gcd(n,n+i) == 1)
k++;
if(k == m) {
return n+i;
}
i++;
}
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
ll k, m, n;
scanf("%lld %lld",&k,&m);
ll s = k^m;
bool flag = true;
for(ll i = -512; i <= 512; i++) {
n = k+i;
if(n<1)
continue;
ll g = (f(n,m) - n)^n;
if(g == k) {
printf("%lld\n",n);
flag = false;
//i = 2000;
break;
}
}
if(flag) {
printf("-1\n");
}
}
return 0;
}