Connecting...

[ARC150B] Make Divisible解题报告

[ARC150B] Make Divisible解题报告

前言

这题非常好,窝被根号分治骗进来,写了数论分块而去,感觉题解区大家思路多少都有点不同。我写的数论题很少,看不懂大佬的过程,只能手推了,下面是蒟蒻的过程。

思路

先看 \(b<=a\) 时,吧 \(b\) 补齐 \(a\) 即可,之后默认 \(b>a\) 虽然没啥用。

然后自然有柿子 \(k(A+X)=(B+Y)\) 其中 \(X,Y>=0\)\(k\in \mathbb{Z^+}\) (打不来了,大抵如此)

然后很自然就是用 \(X,Y>0\) 推出 \(k\) 的范围,试一下发现很好解出

\[\left\lfloor\frac{B+Y}{A}\right\rfloor\ge k\ge\left\lceil\frac{B}{A+X}\right\rceil \]

然后感性理解一波,\(B+Y=\left\lceil\frac{B}{A+X}\right\rceil\times(A+X)\)

因为此时 \((A+X)\mid(B+Y)\)

那么完整柿子

\[X+Y=X+\left\lceil\frac{B}{A+X}\right\rceil\times(A+X)-B \]

发现向上取整可以整数分块,怎么搞?感性理解下面柿子

\(\left\lceil\frac{a}{b}\right\rceil=\left\lfloor\frac{a}{b}+\frac{b-1}{b}\right\rfloor=\left\lfloor\frac{a-1}{b}+1\right\rfloor\)

分块时某一段的左端点一定是一段里面最优的

代码

在实现上出了点锅,在r取到最后的时候还要再算一次

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int t;
int main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>t;
	while(t--){
		ll a,b;
		cin>>a>>b;
		if(a>=b){cout<<a-b<<"\n";continue;}//b不足就补齐
		ll ans=1e18,r;
		for(ll l=a;l<=b-1;l=r+1){
			r=min(b-1,(b-1)/((b-1)/l));
			ans=min(ans,(l-a)+(1+(b-1)/l)*l-b);
		}r++;
		ans=min(ans,(r-a)+(1+(b-1)/r)*r-b);
		cout<<ans<<"\n";
	}
	return 0;
} 

\(\LaTeX\)

posted @ 2024-07-27 13:11  余亦宸  阅读(19)  评论(0)    收藏  举报