CF1152C Neko does Maths

欢迎您来我的网站看这篇题解!

Problem

Neko has two integers a a a and b b b. His goal is to find a non-negative integer k k k such that the least common multiple of a + k a+k a+k and b + k b+k b+k is the smallest possible. If there are multiple optimal integers k k k, he needs to choose the smallest one.

Given his mathematical talent, Neko had no trouble getting Wrong Answer on this problem. Can you help him solve it?

k ≥ 0 k\ge 0 k0 使 min ⁡ lcm ⁡ ( a + k , b + k ) \min\operatorname{lcm}(a+k,b+k) minlcm(a+k,b+k),若有多个 k k k,取最小的。

1 ≤ a , b ≤ 1 0 9 1\le a,b\le10^9 1a,b109

Solution

这道题还是挺妙的,用到了几个知识点。

  1. lcm ⁡ ( a + k , b + k ) = ( a + k ) ( b + k ) gcd ⁡ ( a + k , b + k ) \operatorname{lcm}(a+k,b+k)=\frac{(a+k)(b+k)}{\gcd(a+k,b+k)} lcm(a+k,b+k)=gcd(a+k,b+k)(a+k)(b+k)
  2. ( a + k ) ( b + k ) gcd ⁡ ( a + k , b + k ) = ( a + k ) ( b + k ) gcd ⁡ ( b + k , a − b ) \frac{(a+k)(b+k)}{\gcd(a+k,b+k)}=\frac{(a+k)(b+k)}{\gcd(b+k,a-b)} gcd(a+k,b+k)(a+k)(b+k)=gcd(b+k,ab)(a+k)(b+k)

我们将最小公倍数转化为最大公因数,且利用辗转相除法得出了一个定值 a − b a-b ab

如果某个 k k k 会使得原式变小,那么肯定会使得 gcd ⁡ ( b + k , a − b ) > 1 \gcd(b+k,a-b)>1 gcd(b+k,ab)>1,也就是说 b + k b+k b+k a − b a-b ab 具有公因数。我们只需要枚举这样的 b + k b+k b+k 就好,缩小了枚举的范围。

具体地,我们枚举 a − b a-b ab 的因数 x x x;为了使 b + k b+k b+k x x x 的(最小的)倍数:

  • b%k==0 k = 0 k=0 k=0
  • b%k!=0 k = ( b − ⌊ b x ⌋ ⋅ x ) k=(b-\lfloor \frac bx\rfloor\cdot x) k=(bxbx)

我们使用 O ( a − b ) O(\sqrt{a-b}) O(ab ) 的时间枚举 a − b a-b ab 的因数,计算满足条件的最小的 k k k,并尝试用此时的 lcm ⁡ ( a + k , b + k ) \operatorname{lcm}(a+k,b+k) lcm(a+k,b+k)​ 去更新答案即可。

需要注意特判 a = b a=b a=b 的情况,此时 a − b = 0 a-b=0 ab=0,不会存在这样的 k k k

Code

LL gcd(LL a,LL b)
{
	if(!a) return b;
	if(!b) return a;
	return gcd(b,a%b);
}

LL lcm(LL a,LL b)
{
	return a*b/gcd(a,b);
}

LL k,minlcm;
LL a,b;
void test(LL x)
{
	LL aa=b/x;
	LL bb=b%x;
	if(bb) aa++;
	aa*=x;
	LL kk=aa-b;
	if(lcm(a+kk,b+kk)<minlcm||(lcm(a+kk,b+kk)==minlcm&&kk<k))
	{
		k=kk;
		minlcm=lcm(a+kk,b+kk);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cout.precision(10);
	int t=1;
//	cin>>t;
	while(t--)
	{
		k=100000000000ll;
		cin>>a>>b;
		if(a==b)
		{
			cout<<0<<endl;
			return 0;
		}
		if(a<b) swap(a,b);
		minlcm=lcm(a,b);
//		cout<<minlcm<<endl;
		for(LL i=1;i*i<=a-b;i++)
		{
			if((a-b)%i==0)
			{
				test(i);
				test((a-b)/i);
			}
		}
		cout<<k<<endl;
	}
	return 0;
}

相关推荐

  1. CF1152C Neko does Maths

    2024-07-23 00:42:04       17 阅读
  2. <span style='color:red;'>CI</span>/<span style='color:red;'>CD</span>

    CI/CD

    2024-07-23 00:42:04      45 阅读
  3. 题目 1159: 偶数求和

    2024-07-23 00:42:04       38 阅读
  4. 1162. 地图分析

    2024-07-23 00:42:04       51 阅读
  5. 题目 1752: 对称矩阵

    2024-07-23 00:42:04       30 阅读
  6. C++ P1152 欢乐的跳

    2024-07-23 00:42:04       27 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-23 00:42:04       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-23 00:42:04       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-23 00:42:04       45 阅读
  4. Python语言-面向对象

    2024-07-23 00:42:04       55 阅读

热门阅读

  1. [技术总结] C++ 使用经验

    2024-07-23 00:42:04       16 阅读
  2. STL set

    2024-07-23 00:42:04       12 阅读
  3. 【Devops系统】如何构建Devops系统

    2024-07-23 00:42:04       16 阅读
  4. 面了抖音算法岗,被疯狂拷打。。。

    2024-07-23 00:42:04       18 阅读
  5. 使用 kapt 注解生成依赖注入代码

    2024-07-23 00:42:04       13 阅读
  6. Android GlSurfaceView渲染YUV图形

    2024-07-23 00:42:04       15 阅读
  7. iview中Checkbox组件设置不勾选是0,勾选是1

    2024-07-23 00:42:04       14 阅读
  8. 数学基础 -- 导数伪装的极限之变量替换

    2024-07-23 00:42:04       11 阅读
  9. 2024.7.20-22学习日报

    2024-07-23 00:42:04       10 阅读
  10. Linux-查看dd命令进度

    2024-07-23 00:42:04       15 阅读