题目
D. Lucky Chains
time limit per test
4 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output
Let's name a pair of positive integers (x,y)(x,y) lucky if the greatest common divisor of them is equal to 11 (gcd(x,y)=1gcd(x,y)=1).
Let's define a chain induced by (x,y)(x,y) as a sequence of pairs (x,y)(x,y), (x+1,y+1)(x+1,y+1), (x+2,y+2)(x+2,y+2), ……, (x+k,y+k)(x+k,y+k) for some integer k≥0k≥0. The length of the chain is the number of pairs it consists of, or (k+1)(k+1).
Let's name such chain lucky if all pairs in the chain are lucky.
You are given nn pairs (xi,yi)(xi,yi). Calculate for each pair the length of the longest lucky chain induced by this pair. Note that if (xi,yi)(xi,yi) is not lucky itself, the chain will have the length 00.
Input
The first line contains a single integer nn (1≤n≤1061≤n≤106) — the number of pairs.
Next nn lines contains nn pairs — one per line. The ii-th line contains two integers xixi and yiyi (1≤xi<yi≤1071≤xi<yi≤107) — the corresponding pair.
Output
Print nn integers, where the ii-th integer is the length of the longest lucky chain induced by (xi,yi)(xi,yi) or −1−1 if the chain can be infinitely long.
Example
input
Copy
4 5 15 13 37 8 9 10009 20000output
Copy
0 1 -1 79Note
In the first test case, gcd(5,15)=5>1gcd(5,15)=5>1, so it's already not lucky, so the length of the lucky chain is 00.
In the second test case, gcd(13+1,37+1)=gcd(14,38)=2gcd(13+1,37+1)=gcd(14,38)=2. So, the lucky chain consists of the single pair (13,37)(13,37).
思路 (线性筛+分解质因子)
\(Lemma:更相损减法:(a, b) = (b, a - b)\)
\(x < y\)
\((x + k, y + k) = (x + k, y - x)\)
问题转化为求最小的\(k\)使得\(d \mid x + k\), 即\(min(d - x \bmod d)\), 且\(d \mid x + k\)(\(d\)为\(y - x\)的因子)
直接枚举的因子得话
复杂度\(O(n\sqrt{x})\)显然会超时
对于\(y - x\)的素因子\(p\), 若因子\(d | (x + k)\),则存在\(p | d\), 所以\(p | (x + k)\)。
所以我们只枚举\(y - x\)的素因子来求, 因为 \(\pi(\sqrt{1e7}) ≈ 500\), 分解质因数,勉强\(2s\)可以过
我们可以优化以下分解质因子,可以使复杂度降到\(O(nlogn)\), 我们可以在预处离素数时,处理好每个数的最小质因数,然后分解质因子的时候通过数组下标得到最小质因数进行分解
部分参考 zhihu
Code
朴素版本:
#include <bits/stdc++.h>
#define FASTIO \
std::ios::sync_with_stdio(0); \
std::cin.tie(0); \
std::cout.tie(0);
using i64 = long long;
const int N = 1e7 + 10, MAXN = 1e7 + 10;
int primes[N], cnt;
bool st[N];
void get_primes(int n) {
for(int i = 2; i <= n; i ++) {
if(!st[i]) primes[cnt ++] = i;
if(cnt > 10000) break;
for(int j = 0; primes[j] <= n / i; j ++) {
st[primes[j] * i] = true;
if(i % primes[j] == 0) break;
}
}
}
// void init() {
// for(i64 i = 1; i <= MAXN; i ++) {
// for(i64 j = i; j <= MAXN; j += i) {
// fractors[j].push_back(i);
// }
// }
// }
void solve() {
int x, y;
std::cin >> x >> y;
if(y - x == 1) {
std::cout << "-1" << "\n";
return;
} else if(std::__gcd(x, y) > 1) {
std::cout << "0" << "\n";
return;
}
int mx = 0x3f3f3f3f;
int b = y - x, cur = 0;
while(primes[cur] <= sqrt(b)) {
if(b % primes[cur]) {
cur ++;
continue;
}
while(b % primes[cur] == 0) {
b /= primes[cur];
}
mx = std::min(mx, primes[cur] - x % primes[cur]);
cur ++;
}
if(b > 1) {
mx = std::min(mx, b - x % b);
}
std::cout << (mx == 0x3f3f3f3f?-1:mx) << "\n";
}
int main() {
FASTIO;
get_primes(10000000);
int _;
std::cin >> _;
while(_ --) {
solve();
}
}
优化分解质因子,用最小质因子来求:
#include <bits/stdc++.h>
#define FASTIO \
std::ios::sync_with_stdio(0); \
std::cin.tie(0); \
std::cout.tie(0);
using i64 = long long;
const int N = 1e7 + 10, MAXN = 1e7 + 10;
int primes[N], cnt, pe[N];
bool st[N];
void get_primes(int n) {
for(int i = 2; i <= n; i ++) {
if(!st[i]) primes[cnt ++] = i, pe[i] = i;
for(int j = 0; primes[j] <= n / i; j ++) {
st[primes[j] * i] = true;
pe[primes[j] * i] = primes[j];
if(i % primes[j] == 0) break;
}
}
}
void solve() {
int x, y;
std::cin >> x >> y;
if(y - x == 1) {
std::cout << "-1" << "\n";
return;
} else if(std::__gcd(x, y) > 1) {
std::cout << "0" << "\n";
return;
}
int mx = 0x3f3f3f3f;
int b = y - x, cur = 0;
// while(primes[cur] <= sqrt(b)) {
// if(b % primes[cur]) {
// cur ++;
// continue;
// }
// while(b % primes[cur] == 0) {
// b /= primes[cur];
// }
// mx = std::min(mx, primes[cur] - x % primes[cur]);
// cur ++;
// }
// if(b > 1) {
// mx = std::min(mx, b - x % b);
// }
while(b > 1) {
mx = std::min(mx, pe[b] - x % pe[b]);
int pp = pe[b];
while(b % pp == 0) b /= pp;
}
std::cout << (mx == 0x3f3f3f3f?-1:mx) << "\n";
}
int main() {
FASTIO;
get_primes(10000000);
int _;
std::cin >> _;
while(_ --) {
solve();
}
}
浙公网安备 33010602011771号