Educational Codeforces Round 139 D. Lucky Chains

Lucky Chains

题面翻译

给定两个数·a, b,(a, b给到了1e7)执行如下语句:

while(gcd(a, b) == 1) a++, b++, cnt++ ;
求出cnt的值。

样例 #1

样例输入 #1

4
5 15
13 37
8 9
10009 20000

样例输出 #1

0
1
-1
79

分析:

gcd的性质:gcd(a, b) == gcd(a, b - a)
因此gcd(a + k, b + k) == gcd(a + k, b - a)至此a - b为定值,
因此我们只需要判断出对于每一个b - a的质因子p,(a + k) % p == 0时k的最小值,
也就是求p - a % p的最小值

  • 这里用到了分解质因子,首先线性筛一遍1e7内的质数,有3200 * 3200 > 1e7

线性筛+分解质因子O(500n)
参考解析
参考证明

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define mst(x, y) memset(x, y, sizeof x)
#define endl '\n'
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 100010, INF = 0x3f3f3f3f3f3f3f3f, MOD = 1e9 + 7;
int T;
int a, b;
int primes[N], cnt;
bool st[N];
void init()
{
    for (int i = 2; i <= 3200; i++)
    {
        if (!st[i])
            primes[cnt++] = i;
        for (int j = 0; primes[j] * i < N; j++)
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0)
                break;
        }
    }
}
void solve()
{
    cin >> a >> b;
    if (a > b)
        swap(a, b);
    if (b - a == 1)
    {
        cout << "-1" << endl;
        return;
    }
    else if (__gcd(a, b) != 1)
    {
        cout << "0" << endl;
        return;
    }
    else
    {
        int t = b - a;
        int res = INF, curr = 0;
        while (primes[curr] <= sqrt(t))
        {
            if (t % primes[curr])
            {
                curr++;
                continue;
            }
            while (t % primes[curr] == 0)  // 分解质因子
                t /= primes[curr];
            res = min(res, primes[curr] - a % primes[curr]);
            curr++;
        }
        if (t > 1)
            res = min(res, t - a % t);
        cout << res << endl;
    }
}
signed main()
{
    FAST;
    init();
    cin >> T;
    while (T--)
        solve();
    return 0;
}
posted @ 2022-12-22 20:57  347Foricher  阅读(102)  评论(0)    收藏  举报