小凯的疑惑
题目背景:
NOIP2017 D1T1
分析:结论 or 扩展欧几里得
正解答案就是x * y - x - y,可以用剩余系比较简单的证明,然而我用了扩欧来写,然后今天花了一段时间来证明他是等价的。下面来讲讲我自己的结论证明。
首先因为可以构造出的每一个数,都应该是形如ax + by的形式,那么要将ax + by变成ax + by + 1实际上就是减少一些x变成y,或者是减少一些y,变成x,那么我可以用扩欧获得满足条件的最小的ax - by = 1, cy - dx = 1, a, b, c, d都可以很方便的求得。然后我们就可以发现我们每一次的+1操作应该都是通过将by变成ax,或者dx变成cy来达成,那么最大的不能实现加一操作的数应该就是(b - 1)y + (d - 1)x,所以(b - 1)y + (d - 1)x + 1是一定不能表出的,那么如何证明这一定是最大的,我们考虑证明(b - 1)y + (d - 1)x + 2是一定能够被表出的,观察上面获得的等式ax - by = 1, dx - cy = -1, 那么(a + d)x = (b + c)y,显然a < y, b < x, d < y, c < x,(x, y) = 1,那么a + d = y, b + c = x,下面我们来证明一个结论,存在a >= y / 2, 且b >= x / 2, 或者d >= y / 2, 且c >= x / 2。我们不妨设x > y,a >= d,假设结论不成立,则必然存在a > y / 2,b < x / 2,稍作放缩可以获得,a >= (y + 1) / 2,b <= (x - 1) / 2,代入等式ax = by + 1,那么ax >= (xy + x) / 2,by + 1 <= (xy - y) / 2 + 1,那么xy + x <= xy - y + 2,x + y <= 2,因为原题数据在正整数范畴,只有1,1满足条件,但是数据保证存在这么一个值,所以1,1不是可行数据,所以结论在本题数据的范畴下是成立的,考虑这个结论有什么意义。如果要得到+2的操作,只能通过2by转移到2ax,或者通过2dx转移到2cy,因为,存在上述结论,如果满足的是a,b那么说明2 * b >= x,且2 * a >= y,那么我们就可以通过(2b - x) * y转移到(2a - y) * x,因为2 * b < x + b的,那么2 * b - x < b,同理2 * a - y < a,所以一定可以达成+2的转移,到此,得证(b - 1)y + (d - 1)x + 1为最大的不可行数,然后我们来证明上面等式与x * y - x - y等价,考虑(a + d)x = xy = by + 1 + dx,所以(b - 1)y + (d - 1)x + 1 = xy - x - y,得证。(感觉评论区会有一群骂我zz的人······)
Source
/*created by scarlyw
*/
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cctype>
#include <queue>
#include <vector>long long a, b, x1, x2, x, y, a1, a2, temp;
inline void ext_gcd(long long a, long long b) {if (b == 0) x = 1, y = 0;else ext_gcd(b, a % b), temp = x, x = y, y = temp - a / b * y;
}inline void solve() {std::cin >> a >> b;if (a == 1 || b == 1) std::cout << 0, exit(0);ext_gcd(a, b), x1 = (x % b + b) % b, a1 = (a * x1 - 1) / b - 1;ext_gcd(b, a), x2 = (x % a + a) % a, a2 = (b * x2 - 1) / a - 1;std::cout << a1 * b + a2 * a + 1;
}int main() {
// freopen("math.in", "r", stdin);
// freopen("math.out", "w", stdout);solve();return 0;
}