for (int i = 0; i <= a; i++) { for (int j = 0; j <= a; j++) { if (i * i + j * j == a * a && i && j) { int gcd = __gcd(i, j); int p = -i / gcd, q = j / gcd; int y = p, x = q; while (x * x + y * y < b * b) { x += q, y += p; } if (x * x + y * y == b * b && x != i && y != j) { cout << "YES\n"; cout << 0 << ' ' << 0 << "\n"; cout << i << ' ' << j << "\n"; cout << x << ' ' << y << "\n"; return; } } } }
cout << "NO\n"; }
signedmain(){ ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int T = 1; // cin >> T; while (T--) solve(); return0; }
奶牛速度足够快。可以使得对于任意一个顶点 (x,y) 在到达 y 轴时,都小于此时奶牛的 y 值,用时间来表示就是 uy≤vx,即 y≤vux,表示凸包上所有的顶点都在直线 y=vu 的下方
凸包速度足够快。可以使得对于任意一个顶点 (x,y) 在到达 y 轴时,都大于此时奶牛的 y 值,用时间来表示就是 uy≥vx,即 y≥vux,表示凸包上所有的顶点都在直线 y=vu 的上方
上述两种都不满足,即直线 y=vu 与凸包相交。此时奶牛就不能一直全速(u)前进到终点了,需要进行一定的减速 or 返回操作。有一个显然的结论就是,对于减速 or 返回的操作,都可以等价于后退一段距离后再全速(u)前进,因此对于需要减速 or 返回的操作,我们只需要计算出当前状态下应该后退的距离即可。再简洁的,我们就是需要平移直线 y=vu,显然只能向下平移而非向上平移,因此其实就是计算出直线 y=vu+b 的截距 b 使得最终的直线 y=vu+b 满足第二种条件即可。那么如何计算这个 b 呢?很显然我们可以遍历每一个顶点取满足所有顶点都在直线 y=vu+b 上方的最大截距 b 即可。