【Codeforces】Educational Codeforces Round 139 (Div. 2) D. Lucky Chains | 质因数分解

81 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

【Codeforces】Educational Codeforces Round 139 (Div. 2) D. Lucky Chains | 质因数分解

题目链接

Problem - D - Codeforces

题目

image.png

题目大意

给定 xxyy,求最小的非负整数 kk 使得

gcd(x+k,y+k)>1gcd(x+k,y+k)>1

如果 kk 不存在,输出 -1

思路

假设

gcd(x+k,y+k)=t>1gcd(x+k,y+k)=t>1

tt(x+k)(x+k) 的因数,也是 (y+k)(y+k) 的因数。那么一定有

x%t=y%t(yx)%t=0\begin{aligned} x\%t&=y\% t\\ (y-x)\%t&=0 \end{aligned}

t(yx)t\mid(y-x)

所以当且仅当 t(yx)t\mid(y-x) 时,未知数为 kk 的方程 gcd(x+k,y+k)=tgcd(x+k,y+k)=t 有非负整数解,最小的非负整数解为 k=tx%tk=t-x\%t

对于任三个正整数 a,b,c>1a,b,c>1,显然有

a×bc%(a×b)min(ac%a,bc%b)a\times b-c\%(a\times b)\ge min(a-c\%a,b-c\%b)

所以我们只需要对 yxy-x 所有的质因数分别求出对应的 tt,取最小值即可。质因数分解时,可以先把 1e7\sqrt{1e7} 范围内的质数先筛出来加快求解。(也可以使用线性筛记录每个合数的最小质因数,直接 O(logn)O(logn) 进行质因数分解)。

最终解题流程为:

  • gcd(x,y)>1gcd(x,y)>1时,我们直接输出 0
  • yx=1y-x=1 时,我们直接输出 -1
  • 其他情况我们枚举 yxy-x 的质因数,求解最小的 tt 即可。

代码

#include <stdio.h>
#include <algorithm>
using namespace std;
using LL=long long;
const int N=1e6+5,M=3201;
const LL mod=1e9+7;
int n,m,k;
int v[M],p[M],tot;
int gcd(int a,int b)
{
	if (b==0) return a;
	return gcd(b,a%b);
}
LL solve()
{
	scanf("%d%d",&n,&m);
	if (gcd(n,m)!=1) return 0;
	k=m-n;
	if (k==1) return -1;
	int ans=k-n%k;
	for (int i=1;i<=tot&&p[i]*p[i]<=k;++i)
	{
		if (k%p[i]!=0) continue;
		while (k%p[i]==0) k/=p[i];
		ans=min(ans,p[i]-n%p[i]);
	}
	if (k!=1) ans=min(ans,k-n%k);
	return ans;
}
int main()
{
	int T=1;
	n=M-1;
	for (int i=2;i<=n;++i)
	{
		if (!v[i]) p[++tot]=i;
		for (int j=1;j<=tot&&i*p[j]<=n;++j)
		{
			v[i*p[j]]=1;
			if (i%p[j]==0) break;
		}
	}
	scanf("%d",&T);
	while (T--) printf("%lld\n",solve());
	return 0;
}