Croatian Open Competition in Informatics (COCI) 2020/2021 — Round #2

(sf Also 2021.6.19)

(sf A-Euklid)

解法

这个构造真的好精妙啊。

不妨设

[b=gleft lceil frac{h^k}{g} ight ceil,a=hb+g ]

那么 (frac{b}{g}=left lceil frac{h^k}{g} ight ceil,frac{a}{g}=hleft lceil frac{h^k}{g} ight ceil+1)。只需要二者互质就能达到 (gcd(a,b)=g) 的条件。容易发现这在 (left lceil frac{h^k}{g} ight ceil>1) 时成立。

那我们不妨取最小的 (k) 使得 (left lceil frac{h^k}{g} ight ceil>1) 成立,此时可以推出 (g<h^k)(h^k) 不会很大,因为即使 (h=g) 这种比较极端的情况也有 (left lceil frac{h^2}{g} ight ceil>1)(h^2le 4 imes 10^{10})

此时有 (h^kle b<2 imes h^k)。对于后一个范围是因为 (b<h^k+g<2 imes h^k)

这有什么用呢?我们尝试带入 (a,b) 来计算这个函数。

首先有 ( ext{R}(a,b)= ext{R}(b,h)),因为 (frac{g}{b}<1)。之后将 (b) 不断除以 (h),容易发现 (b) 的取值范围是同构的,最后一次有 (k=1) 就可以得到 ( ext{R}(h,1)) 也即达到我们的目标。

代码

#include <bits/stdc++.h>
using namespace std;

#define rep(i,_l,_r) for(int i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)

int read() {
	int x=0; bool f=0; char s;
	while((s=getchar())>'9' or s<'0') f|=(s=='-');
	while(s>='0' and s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
	return f?-x:x;
}

void write(int x) {
	if(x<0) return (void)(putchar('-'),write(-x));
	if(x>9) write(x/10);
	putchar(x%10^48);
}

typedef long long ll;

int main() {
	freopen("euklid.in","r",stdin); freopen("euklid.out","w",stdout);
	rep(T,1,read()) {
		ll g=read(),h=read(),tmp=h;
		while(tmp<=g) tmp=tmp*h;
		ll a=((tmp-1)/g+1)*g,b=a*h+g;
		printf("%lld %lld
",a,b); 
	}
	return 0;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/14903516.html