D. Lucky Chains(GCD 数论)[Educational Codeforces Round 139 (Rated for Div. 2)]

题目如下:

在这里插入图片描述

题解 or 思路:

g c d ( a , b ) = g c d ( a , a − b ) gcd(a, b) = gcd(a, a - b) gcd(a,b)=gcd(a,ab)
题目要我们计算 g c d ( a + k , b + k ) = 1 gcd(a + k, b + k) = 1 gcd(a+k,b+k)=1 的最小 k k k 是多少
g c d ( a + k , b + k ) = g c d ( a + k , a − b ) gcd(a + k, b + k) = gcd(a + k, a - b) gcd(a+k,b+k)=gcd(a+k,ab)
根据这个等式,问题就转换成:
d i f dif dif 等于 a b s ( a − b ) abs(a - b) abs(ab)
p p p d i f dif dif 的一个质因子
我们要计算 p − a % p p - a \% p pa%p 的最小值

AC代码

代码一:

线性筛 + 根号下暴力找质因子

const int N = 100009;
const int maxn = 3200;
int a, b;
int prime[N];
bool sf[N];
int num;
void sushu()
{
    sf[1] = 1;
    sf[0] = 1;
    for (int i = 2; i <= maxn; i++)
    {
        if (!sf[i])
            prime[++num] = i;
        for (int j = 1; j <= num; j++)
        {
            if (i * prime[j] > maxn)
                break;
            sf[i * prime[j]] = 1;
            if (i % prime[j] == 0)
                break;
        }
    }
}
void solve()
{
	cin >> a >> b;
	int dif = abs(a - b);
	if (dif == 1)
	{
		cout << "-1\n";
		return;
	}
	if (__gcd(a, b) != 1)
	{
		cout << "0\n";
		return;
	}
	int ans = 0x3f3f3f3f;
	int idx = 1;
	while (prime[idx] * prime[idx] <= dif)
	{
		if (dif % prime[idx] == 0)
		{
			ans = min(ans, prime[idx] - a % prime[idx]);
			while (dif % prime[idx] == 0)
				dif /= prime[idx];
		}
		idx++;
	}
	if (dif > 1)
		ans = min(ans, dif - a % dif);
	
	cout << ans << '\n';
}
int main()
{
	buff;
	sushu();
	int _;
	cin >> _;
	while (_--)
		solve();
}

代码二:

更改筛法,记录每一个数的最小质因子
速度更快 空间换时间

const int maxn = 1e7 + 5;
int prime[maxn], p[maxn], num;
void sushu()
{
    p[0] = p[1] = -1;
    for (int i = 2; i < maxn; i++)
    {
        if (!p[i])
            prime[++num] = i, p[i] = i;
        for (int j = 1; j <= num && prime[j] * i < maxn; j++)
        {
            p[i * prime[j]] = prime[j];
            if (i % prime[j] == 0)
                break;
        }
    }
}
void solve()
{
    int a, b;
    cin >> a >> b;
    int dif = abs(a - b);
    if (dif == 1)
    {
        cout << -1 << '\n';
        return;
    }
    if (__gcd(a, b) != 1)
    {
        cout << 0 << '\n';
        return;
    }

    int ans = 0x3f3f3f3f;
    while (dif > 1)
    {
        ans = min(ans, p[dif] - a % p[dif]);
        int tt = p[dif];
        while (dif % tt == 0)
            dif /= tt;
    }
    cout << ans << '\n';
}
int main()
{
    buff;
    sushu();
    int _;
    cin >> _;
    while (_--)
        solve();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joanh_Lan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值