表白的数论
题意 : 从s走到t, 距离为c,现在每步只能走a,b,a+b三种长度的步数。 a,b,c均为整数,现在问至少走多少步能到达终点。
思路: 开始的时候一样就看出了用扩展欧几里德做,算出来ax+by=c的整数解,然后再波动,算的过程中注意a+b的情况并上。 后来一直wa。
后来又换了一种做法,即看成这个人可以走三种情况a,b或a,a+b,或b,a+b。
这三种情况算出后再进行波动。 第二种想法是严密的,没有漏洞出现。
AC代码:
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; typedef long long LL; const LL INF = 1LL<<62; LL s, t, a, b; LL gcd(LL &x,LL &y,LL a,LL b) { if(b==0) { x = 1; y = 0; return a; } LL d = gcd(x,y,b,a%b); LL t = x; x = y; y = t - a/b*y; return d; } LL abs(LL a) { return a > 0 ? a:-a; } void init() { scanf("%lld%lld%lld%lld", &s, &t, &a, &b); } LL get(LL a, LL b) { LL c, x, y, g, ans, xx, yy; c = s - t; if(c < 0) c = -c; g = gcd(x, y, a, b); if(c % g) { return INF; } a /= g; b /= g; c /= g; x = x*c; y = y*c; x = (x%b + b)%b; y = (y%a + a)%a; ans = INF; for(int i=-5; i<=5; i++) { xx = x+b*i; yy = (c - xx*a)/b; ans = min(ans,abs(xx) + abs(yy)); } for(int i=-5; i<=5; i++) { yy = y+a*i; xx = (c - yy*b)/a; ans = min(ans, abs(xx) + abs(yy)); } return ans; } int main() { int t; LL ans; scanf("%d", &t); while(t--) { init(); ans = get(a,b); ans = min(ans, get(a+b,a) ); ans = min(ans, get(a+b,b) ); if(ans == INF) printf("-1\n"); else printf("%lld\n", ans); } return 0; }


浙公网安备 33010602011771号