【题目描述】
小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。每种金币小凯都有无数个。在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。
【输入】
输入数据仅一行,包含两个正整数 aa 和 bb,它们之间用一个空格隔开,表示小凯手中金币的面值。
【输出】
输出文件仅一行,一个正整数 NN,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。
【输入样例】
3 7
【输出样例】
11
【提示】
【样例说明】
小凯手中有面值为33和77的金币无数个,在不找零的前提下无法准确支付价值为 1、2、4、5、8、111、2、4、5、8、11的物品,其中最贵的物品价值为1111。
比1111贵的物品都能买到,比如:
12=3×4+7×0
13=3×2+7×1
14=3×0+7×2
15=3×5+7×0
【数据范围】
对于 30% 的数据:1≤a,b≤501≤a,b≤50;
对于 60% 的数据: 1≤a,b≤10,0001≤a,b≤10,000;
对于 100% 的数据:1≤a,b≤1,000,000,0001≤a,b≤1,000,000,000。
题解
首先,我们发现这两个数是互质的,并且有无限个。很容易想到不定方程 ax + by = gcd(a, b)ax+by=gcd(a,b) ,其中 gcd(a, b) = 1gcd(a,b)=1 。
然后我们考虑,对于所有可行的能被 aa 和 bb 表示出来的数 kk ,都存在 x \geq 0, y \geq 0,ax + by = kx≥0,y≥0,ax+by=k。
现在我们要构造的是最大的不合法的数,显然,这个数 + 1+1 一定是一个合法的数,转化成了求最大的减一后不合法的数。
由于这个数 kk 一定是合法的,所以满足性质
\exists x \geq 0, \exists y \geq 0,ax + by = k∃x≥0,∃y≥0,ax+by=k
那么如果 k-1k−1 合法,那么 k - 1k−1 可以表示成
a \left ( x - x' \right ) + b \left ( y - y' \right ) = ka(x−x′)+b(y−y′)=k
或
a \left ( x - x'' \right ) + b \left ( y - y'' \right ) = ka(x−x′′)+b(y−y′′)=k
其中 x',y'x′,y′ 表示 ax + by = 1ax+by=1 的 xx 最小且非负的整数解; x'',y''x′′,y′′ 表示 ax + by = 1ax+by=1 的 yy 最小且非负的整数解。
那么现在只需要让 x - x'< 0x−x′<0 并且 y - y'' < 0y−y′′<0 即可
那么最后的最大的减一后不合法的数就是
a \left ( x' - 1 \right ) + b \left ( y'' - 1 \right )a(x′−1)+b(y′′−1)
那么最后的答案就是
a \left ( x' - 1 \right ) + b \left ( y'' - 1 \right ) - 1a(x′−1)+b(y′′−1)−1
证明:
首先充分性成立。
然后证明必要性:若a \left ( x' - 1 \right ) + b \left ( y'' - 1 \right )a(x′−1)+b(y′′−1)不是最大的减一后不合法的数,那么一定存在一个更大的数,显然该数的 aa 的系数大于 x' - 1x′−1 或 bb 的系数大于 y'' - 1y′′−1 (如果都小于等于,那么该数不会比当前数大)。显然,减一后仍然是合法的。所以必要性成立。
综上, a \left ( x' - 1 \right ) + b \left ( y'' - 1 \right ) - 1a(x′−1)+b(y′′−1)−1 是最大的不合法的数。
最后代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
long long i, n;
cin >> i >> n;
cout << i*n - i - n;
return 0;
}
or
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
void ex_gcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1, y = 0;
return;
}
ex_gcd(b, a % b, y, x);
y -= (a / b) * x;
}
ll a, b;
int main() {
cin >> a >> b;
if (a > b) swap(a, b);
ll x, y;
ex_gcd(a, b, x, y);
if (x > 0) {
swap(a, b);
swap(x, y);
}
ll tmp = (-x) / b;
x = x + tmp * b;
y = y - tmp * a;
while (x < 0) x = x + b, y = y - a;
while (x > 0) x = x - b, y = y + a;
ll ans;
ll xx2 = x + b;
ans = a * (xx2 - 1) + b * (y - 1);
cout << ans - 1 << endl;
return 0;
}