目录
题目:
题目描述:
n个案例,每个案例给你一对( x ,y ),请找到最小的 k 使得 gcd( x + k ,y + k )> 1
思路:
gcd性质:
gcd( a , b ) == gcd( a , b - a )
所以:
gcd( x + k , y + k ) == gcd( x + k , y - x )
那么问题就转化成了,如何找到最小的 k ,使得 gcd( x + k , y - x ) > 1
因为 y - x 是一个固定的值,所以此时我们可以枚举 y - x 这个值的所有质因子来作为成为二者的最大公因数,也就是 gcd( x + k , y - x ) 的值,然后对所有枚举的情况中的 k 取最小即可。
至于怎么快速多次的寻找 y - x 的最小质因子,我们可以先初始化一个欧拉筛,然后用一个数组存下所有范围内的数的最小质因数。
思路有了,具体操作请看AC代码
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e7 + 7;
const ll inf = 4e18 + 5;
ll prime[N];//质数数组
ll lp[N];//存放的是当前下标除1以外的最小因子
ll cnt = 1;
//欧拉筛
void init(int x)
{
for (int i = 2; i <= x; i++)
{
if (lp[i] == 0)
{
prime[cnt++] = i;
lp[i] = i;
}
for (int j = 1; j < cnt && prime[j] * i <= x; j++)
{
lp[prime[j] * i] = prime[j];
if (prime[j] % i == 0)//保证每个合数都是由最小的质因子一遍筛掉
break;
}
}
}
int main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
init(N - 1);
ll n;
cin >> n;
while (n--)
{
ll a, b;
cin >> a >> b;
ll c = a - b;
if (b > a)
swap(a, b);
if (c == 1)
{
cout << -1 << "\n";
continue;
}
ll minn = inf;
while (c > 1)
{
int temp = lp[c];
//下面一行右半部分,意在寻找,x最少加多少能到temp的倍数
minn = min(minn, temp - ((a - 1) % temp + 1));//寻找最小的 k
while (c % temp == 0)
c /= temp;
}
cout << minn << '\n';
}
return 0;
}