Loading

[ARC127F] ±AB

statement

有一个数 \(V\),你可以进行若干次 \(+A,-A,+B,-B\) 操作,需要保证任意时刻 \(0\leq V\leq M\),求可以变成那些数字。

solution

  • \(A+B-1\leq M\)

引理一:若 \(x=V+pA+qB\in [0,M]\) ,则 \(V\) 可以变成 \(x\)

\(p,q\) 同号,显然成立。
若不同号,不妨设 \(p>0,q<0\),那么我们可以一直减 \(B\) 直到达到上限或者不能减了,若达到上限,此时一定可以加 \(p\)\(A\),若不能减了,当前的数字 \(v<B\),那么一定可以执行一次加 \(A\),因为 \(v+A\leq A+B-1\leq M\),因此我们就不停地 \(-B,+A\) 直到合法即可。

因为 \(\gcd(A,B)=1\),所以根据裴蜀定理,\(x\) 可以取遍 \([0,M]\)

  • \(A+B-1>M\)

不妨令 \(V=V\bmod A\),显然这和原问题等价。
显然第一步不能选择 \(-A\),且因为 \(A<B\),第一步也不能选择 \(-B\)
不妨设第一次选择了 \(+A\),那么接下来不能选择 \(-A\),因为重复了,也不能 \(+B\),因为 \(A+B-1>M\)。那么只能在 \(+A,-B\) 中选一个,并且显然两个不能同时选,因此对于每个数,都只有唯一的出边,另一种走法 \(+B,-A\) 同理。

引理二:转移图无环

不妨设最小环走了 \(x\)\(+A\)\(y\)\(-B\),则 \(Ax=By\),因为 \(\gcd(A,B)=1\),该方程最小正整数解为 \(B,A\)
但是因为 \(A+B>M+1\),所以环一定重复经过了某些点,与环是最小的矛盾。

引理三:两种走法无交

因为两种走法起点相同,所以若相交,那么一定有环,与上矛盾。

因此可以对两种走法分别计算最远走多少步再加起来就是答案,以 \(+A,-B\) 为例。

不妨设进行了 \(k\)\(+A\),因为走不动了,所以最终的数 \(x\) 一定满足 \(x\in [m-A+1,B-1]\),那么一定进行了 $\lfloor \frac{V+kA}{B} \rfloor $ 次 \(-B\)

也就是说,我们要找最小的 \(k\),满足 $(V+kA)\bmod B+A\geq M+1 $ 。

\(V0=V\bmod B\),若 \(V0+A>M\),显然此时答案为 $\lfloor \frac{V}{B} \rfloor $ 。
否则:

引理四:\(V0+(kA\bmod B)<B\)

若不然,我们先减去 \(B\),然后 \(+A\),一定合法,矛盾。

因此 \((V+kA)\bmod B=V0+(kA\bmod B)\),转为计算 \(L\leq (kA)\bmod B\leq R\) 的最小的 \(k\)

考虑使用类欧求解。

\(B=pA+q,t=\lfloor \frac{kA}{B} \rfloor\),那么 \((kA)\bmod B=kA-Bt=kA-(pA+q)t=A(k-tp)-tq\),可以变成 \(tq\bmod A\in [L',R']\),递归计算。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int Euclid(int A,int B,int L,int R)
{
	if(A==0) return 0;
	A%=B;
	if((L-1)/A!=R/A) return (L+A-1)/A;
	int t=Euclid(B%A,A,(A-R%A)%A,(A-L%A)%A);
	return (1ll*t*B+L+A-1)/A;
}
int walk(int A,int B,int V,int M)
{
	int V0=V%M;
	if(V0+A>M) return V/B;
	int k=Euclid(A,B,M-A-V0+1,B-V0-1);
	return k+(V+1ll*A*k)/B;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int A,B,V,M;
		scanf("%d %d %d %d",&A,&B,&V,&M);
		if(A+B-1<=M)printf("%d\n",M+1);
		else printf("%d\n",walk(A,B,V%A,M)+walk(B,A,V%A,M)+1); 
	}
	return 0;
} 
posted @ 2023-05-28 21:09  Larunatrecy  阅读(15)  评论(0)    收藏  举报