[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\)

浙公网安备 33010602011771号