D. Lucky Chains(gcd + 线性筛)

Problem - D - Codeforces

 

如果一对正整数(x,y)的最大公除数等于1(gcd(x,y)=1),我们就把它们命名为幸运。

让我们把由(x,y)引起的链定义为一个由(x,y), (x+1,y+1), (x+2,y+2), ..., (x+k,y+k)组成的序列,对于某个整数k≥0。

如果链中的所有配对都是幸运的,我们就把这种链称为幸运链。

给你n对(xi,yi)。为每一对计算由这一对引起的最长的幸运链的长度。请注意,如果(xi,yi)本身不是幸运的,那么该链的长度为0。

输入
第一行包含一个整数n(1≤n≤106)--配对的数量。

接下来的n行包含n个配对--每行一个。第i行包含两个整数xi和yi(1≤xi<yi≤107)--对应的配对。

输出
打印n个整数,其中第i个整数是由(xi,yi)引起的最长的幸运链的长度,如果该链可以无限长,则为-1。

例子
输入复制
4
5 15
13 37
8 9
10009 20000
输出拷贝
0
1
-1
79
注意
在第一个测试案例中,gcd(5,15)=5>1,所以它已经不幸运了,所以幸运链的长度是0。

在第二个测试案例中,gcd(13+1,37+1)=gcd(14,38)=2。所以,幸运链由单对(13,37)组成。

题解:
gcd(a,b) = gcd(a ,a - b)

gcd(a+k,b+k) = gcd(a+k,b - a)

设w = abs(a - b)

题目目转化为了a加多少gcd(a+k,w) != 1

我们分解质因数w,遍历w的质因数所有质因数x

找到最小的x - a%x

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
using namespace std;
#define int long long
int f[10000060];
int p[10000600];
int cnt = 0;
void solve()
{
	int a,b;
	cin >> a >> b;
	int k = abs(a - b);
	if(k == 1)
	{
		cout<<"-1\n";
		return ;
	}
	if(__gcd(a,b) != 1)
	{
		cout<<0<<"\n";
		return ;
	}
	int ans = 1e9;
	while(k > 1)
	{
//		cout<<1<<"\n";
		ans = min(ans,p[k] - a%p[k]);
		int tt = p[k];
		while(k%tt == 0)
		k /= tt; 
	}
	cout << ans<<"\n";
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t = 1;
	cin >> t;
	for(int i = 2;i <= 10000000;i++)
	{
		if(!p[i])
		{
			f[++cnt] = i,p[i] = i;
		}
		for(int j = 1;j <= cnt&&f[j]*i <= 10000000;j++)
		{
			p[i*f[j]] = f[j];
			if(i%f[j] == 0)
			break;
		}
	}
    while(t--)
	{
		solve();
	} 
}
//WBBW
//B

11
02-01 246
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值