• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
edu#139-D. Lucky Chains 素数筛+优化分解质因数

题目

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 20000

output

Copy

0
1
-1
79

Note

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();
	}
}
posted on 2023-01-25 20:46  Jack404  阅读(53)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3