题解:P11846 [USACO25FEB] Transforming Pairs P
Solution
简单模拟题。
先考虑
所以如果我们知道了
所以我们直接模拟辗转相除即可。最小步数存在且唯一。
接下来考虑
如果
否则,如果
否则,不妨设
显然一定会出现某一个时刻满足
如果当前
否则,如果
我们会不断执行
此时不妨设
但是我们会计算非常多次
发现我们可以将这样的
而将
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
int T,a,b,c,d;
int solve(int a,int b,int c,int d) {
if(c<0||d<0) return -1;
int ans=0;
if(a==c&&b==d) return 0;
while(c!=0&&d!=0) {
if(c==d) {
if(a==0&&b==c||a==c&&b==0) return ans+1;
if(a==c&&b==d) return ans;
return -1;
}
if(c<d) swap(c,d),swap(a,b);
if(c%d==0&&(a==0&&b==d||a==d&&b==0)) return ans+c/d;
if(b==d&&a<=c&&(c-a)%d==0) return ans+(c-a)/d;
ans+=c/d,c%=d;
}
if(a==c&&b==d) return ans;
return -1;
}
void check(int &ans,int mzx,int nv) {
if(mzx==-1) return ;
ans=min(ans,mzx+nv);
}
struct INFO {int l1,l2,r,d;};
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>T;
while(T--) {
cin>>a>>b>>c>>d;
if(a==c&&b==d) {cout<<0<<'\n';continue ;}
if(a<=0&&b<=0) a=-a,b=-b,c=-c,d=-d;
if(a>=0&&b>=0) {cout<<solve(a,b,c,d)<<'\n';continue ;}
if(a<0) a=-a,b=-b,c=-c,d=-d;
if(c>=0&&d<=0) {cout<<solve(c,-d,a,-b)<<'\n';continue ;}
if(c<0) swap(a,b),swap(c,d),a=-a,b=-b,c=-c,d=-d;
if(c<0&&d>0) {cout<<-1<<'\n';continue ;}
vector<INFO> vc;
int cc=c,dd=d;
while(cc!=0&&dd!=0) {
if(cc<=dd) {dd%=cc;continue ;}
vc.push_back({cc%dd+dd,cc,dd,dd}),cc%=dd;
}
int v=__gcd(c,d);
int ans=LONG_LONG_MAX,al=0;
while(a>0&&b<0) {
if(a+b==0) {check(ans,solve(a,0,c,d),al+1);break ;}
if(a+b<0) {al+=(-b)/a,b=-((-b)%a);continue ;}
if(-b==v) {
int dl1=v,dl2=v,rr=0,ll=v;
if(ll<=a&&(a-ll)%(-b)==0) check(ans,solve(ll,rr,c,d),al+(rr-a)/b);
}
for(auto id:vc) {
int dl1=id.l1-id.r,dl2=id.l2-id.r;
if(dl1<=-b&&-b<=dl2&&(-b-dl1)%id.r==0) {
int rr=id.r,ll=rr-b;
if(ll<=a&&(a-ll)%(-b)==0) check(ans,solve(ll,rr,c,d),al+(rr-a)/b);
}
}
al+=a/(-b),a=a%(-b);
}
if(a>=0&&b>=0) check(ans,solve(a,b,c,d),al);
if(ans!=LONG_LONG_MAX) cout<<ans<<'\n';
else cout<<-1<<'\n';
}
return 0;
}