Codeforces Round 1766 D
Codeforces Round 1766
Educational Codeforces Round 139 (Rated for Div. 2)
D. Lucky Chains
简要题意:
有 \(n\) 组数据 (\(1 \le n \le 10^6\)),每组输入两个数 \(x,y,(1\le x,y \le 10^7)\) 。
找一个最小的自然数 \(k\) ,使得 \(\gcd(x+k,y+k)\neq1\) ,如果找不到,输出 \(-1\) 。
Idea:
考虑 $x $ 和 \(y\) 的差 \(d\) 。
由题意,不妨设 \(m |(x+k)\) ,\(m|(y+k)\) 。
有整除的可见性,得到 \(m|(x+k-y-k)\) 即 \(m|d\) 。
相当于在 \(d\) 的因子中找一个 \(m\) ,使得 \(k\) 最小。
形式化地,有
\[opt(x,y)=\min_{m|d}(x+m-1)/m*m-x
\]
枚举 \(d\) 的因子 \(m\) ,我们得到了一种 \(O(n\sqrt{d})\) 的做法。
Solution:
上面的做法不能通过本题,考虑优化。
考虑 \(d\) 的两个质因子 \(p,t\) (假设有),发现 \(m\) 取 \(p\) 或 \(t\) 时的解肯定不劣于 \(m\) 取 \(pt\) 时的,因为 \(pt|x+k\) 时同时满足 \(p|x+k\) 、\(t|x+k\) ,反之则不一定。所以只枚举 \(d\) 的质因数即可。
如果我们知道值域内每个数的一个质因数,则枚举 \(d\) 的质因子这一问题可以通过递归解决,时间复杂度 \(O(\log w)\) ( \(w\) 为值域,\(1 \le w \le 1e7\) ) 。
预处理值域内每个数的一个质因数可以通过埃氏筛解决,时间复杂度 \(O(w \log w)\) 。
至此,本问题在 \(O(w \log w + n \log w)\) 时间内解决。
Code:
代码很短。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+100;
int a[maxn];
void init(){
for(int i=1;i<maxn;i++) a[i]=i;
for(int i=2;i<maxn;i+=2){
a[i]=2;
}
for(int i=3;i<maxn;i+=2){
if(a[i]!=i){
continue;
}
for(int j=3;i*j<maxn;j+=2){
a[i*j]=i;
}
}
}
int opt(int x,int y){
int d=y-x;
int ans=1e9+100;
if(d==1){
return -1;
}
while(d>1){
ans=min(ans,a[d]-x%a[d]);
if(x%a[d]==0){
ans=0;
break;
}
d/=a[d];
}
return ans;
}
int main(){
init();
int t;
scanf("%d",&t);
int x,y;
while(t--){
scanf("%d%d",&x,&y);
printf("%d\n",opt(x,y));
}
return 0;
}

浙公网安备 33010602011771号