Problem - D - Codeforces
题意是给你a和b,要求__gcd(a+k,b+k)==1的k最多可以增加多少个1
分析:
遇到这种的最大公约数的问题,有很大概率都是推公式,以及使用筛法去把所有的质数筛出来利用质因子去缩短时间
这题就是一个推公式的题目了
gcd有以下性质:
然后对于每一个k,gcd(a+k,b+k)==gcd(a+k,b-a);
所以对于每一个k就是求gcd(a+k,b-a),要求每一个k的增加之后保证gcd(a+k,b-a)==1,即b-a的每个质因子p,保证(a+k)%p==0,求这个k的最小值。因为超过这个最小值,两者的公约数就不是1了,所以求每个质因子共同的k的最小值,就是保证了a+k不是任何一个p的倍数。
(a+k)%p求k的最小值等价于k等于p-a%p(这里可以自己手推,取模的性质,随便想想就可以了)
所以首先用筛法把质数都筛出来,然后对于b-a进行质因数分解,随后求每一个质因子p保证k的最小值(现在开始就不要使用埃氏筛了,太慢。。使用欧拉筛比较好)
然后把longlong注释掉,否则超时(用longlong和endl是十分慢的)
下面是代码(从每日一棵splay那里学的QAQ)
//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
#define IOS ios::sync_with_stdio(false), cin.tie(0);
#include<iostream>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
//#define int long long
typedef long long ll;
typedef pair<int,int> PAII;
const int N=2e6+10,M=5050,INF=1e18,mod=998244353,NN=10000010;
map<int,int> mp;
bool st[N];
int prime[N];
int cnt;
void init()
{
for(int i=2;i<N;i++)
{
if(!st[i]) prime[cnt++]=i;
for(int j=0;prime[j]<=N/i;j++)
{
st[prime[j]*i]=true;
if(i%prime[j]==0) break;
}
}
}
signed main(){
IOS;
int T;
//T=1;
cin>>T;
init();
while(T--)
{
int a,b;
cin>>a>>b;
if(a>b) swap(a,b);
int t=b-a;
if(__gcd(a,b)!=1)
{
cout<<"0\n";
continue;
}
int minn=INF;
int now=0;
while(prime[now]<=sqrt(t))
{
if(t%prime[now]!=0)
{
now++;
continue;
}
while(t%prime[now]==0) t/=prime[now];
minn=min(minn,prime[now]-a%prime[now]);
now++;
}
if(t>1) minn=min(minn,t-a%t);
if(minn==INF) cout<<"-1\n";
else cout<<minn<<"\n";
}
return 0;
}
/*
*/