NOIP2017 D1T1 小凯的疑惑

小凯的疑惑ios

题目背景:spa

NOIP2017 D1T1code

分析:结论 or 扩展欧几里得ci

 

正解答案就是x * y - x - y,能够用剩余系比较简单的证实,然而我用了扩欧来写,而后今天花了一段时间来证实他是等价的。下面来说讲我本身的结论证实。string

首先由于能够构造出的每个数,都应该是形如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 > ya >= d,假设结论不成立,则必然存在a > y / 2b < x / 2,稍做放缩能够得到,a >= (y + 1) / 2b <= (x - 1) / 2,代入等式ax = by + 1,那么ax >= (xy + x) / 2by + 1 <= (xy - y) / 2 + 1,那么xy + x <= xy - y + 2x + y <= 2,由于原题数据在正整数范畴,只有1,1知足条件,可是数据保证存在这么一个值,因此1,1不是可行数据,因此结论在本题数据的范畴下是成立的,考虑这个结论有什么意义。若是要获得+2的操做,只能经过2by转移到2ax,或者经过2dx转移到2cy,由于,存在上述结论,若是知足的是ab那么说明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的人······)it

 

Sourceio

/*
	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;
}