D. Lucky Chains edu139 div2

Problem - D - Codeforces

题意是给你a和b,要求__gcd(a+k,b+k)==1的k最多可以增加多少个1

分析:

遇到这种的最大公约数的问题,有很大概率都是推公式,以及使用筛法去把所有的质数筛出来利用质因子去缩短时间

这题就是一个推公式的题目了

gcd有以下性质:

if(a<b) \quad gcd(a,b)==gcd(a,b-a);

if(a>b) \quad\ gcd(a,b)==gcd(a-b,b);

gcd(a,b)==gcd(b,a%b);

然后对于每一个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;
} 
/*



*/ 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值