首先说这个题用到了 赛瓦维斯特定理
已知a,b为大于1的正整数,gcd(a,b)=1,则使不定方程 ax+by=k 无负整数解的无法构成的最大整数 k=ab−a−b
下面说明能更好理解式子,需要结合题目这么理解:
设小凯必须拿 a 和 b 中的一个,那么它们不能构成的数就是 a*b (因为 ab = a 个 b,或者 b 个 a,在 a,b互质的情况下,ab只能由其中一个数来表示 ),所以当 a 和 b >= 1时,满足无法构成的最大数为 ab 。所以 a-1 和 b-1 >= 0 ,不能构成的最大数就是 ab - a - b(意思就是在两个数都拿一个的基础上,各自都减去一个)
(由于知识点较偏,也是拓展欧几的延伸,所以不做证明,详细证明参考博客)
但是当我们不知道上面的定理,或者忘记了,正常刚看题的时候应该会联想拓展欧几,题意和拓展欧几里得定理的 ax + by = d 有点类似,但又完全想反,因为这道题找的是不能表示的最大值,而此定理找出的是可以表示的所有值。
所以就需要数学推导来寻找答案:
这道题就是为了找 ax + by != c (x > 0,y > 0)时,x,y的值,从而求出 c
对于exgcd来说:ax + by = k (x 或 y < 0)
因为对于 a,b互质的时候,gcd(a,b) = 1,所当 ax + by = 1 时,一定有 x 或 y < 0(看出来就行)
对于a,b不互质的时候,ax + by = gcd(a,b) = d(x 和 y > 0,d > 1),也就能表示 nd,d的任意倍数 (裴蜀定理:一定存在 x ,y > 0 使得 ax + by = d 成立),
所以根据题意可以理解为:找出一个最大的值 k 使得有 ax + by = k,但没有 ax + by = k-1(x 和 y > 0),则这个 k-1 就是我们需要的答案
如果 ax + by = k (x 和 y >0)满足题目表示要求,但没有 ax + by = k-1 (x和y > 0),然后就是求出 k - 1就可以了
如果可以表示成 c - 1 = a(x - x0)+ b(y - y0)(ax0 + by0 = 1)
就一定有
a(x - x1) + b(y - y1)= c-1 (x - x1 < 0 , y - y1 > 0) (1)
a(x - x2) + b(y - y2)= c-1 (x - x2 > 0 , y - y2 < 0) (2)
所以就一定有 x - x0 < x < 0 , y - y0 >= y >= 0(x0,y0不能同号),然后根据上面的两种情况一定找出 x ,y的取值范围。
对于(1)式,ax1 + by1 = 1 (y1为 y 值的最小非负数)
对于(2)式,ax2 + by2 = 1 (x1为 x 值的最小非负数)
(可以通过exgcd求出 x1 和 y1 值)
x - x1 < 0,y - y2 < 0,所以 x 的最大值就是x0 的最小非负整数减一,即 x = x1 - 1,同理, y 的最大值就是 y0 的最小负整数减一,即 y = y2 - 1
求出x,y 满足式子 ax + by = 1 的最小值,就是x1,y2。
将最大满足值带入其中后得到方程
a(x1 - 1)+ b(y2 - 1)
这个值表示可以通过式子 ax + by 表示的最大一个值,在满足 ax0 + by0 = 1 的基础上。
所以满足题意最后结果就是
a(x1 - 1)+ b(y2 - 1)-1
然后就是如何求解最小负整数 x1和 y2 的值
调用 exgcd 求出 x1或者 y2
再通过下面式子
a(x0 + b/gcd * t)+ b(y0 - a/gcd * t)= k (t 属于 N)(等价于 ax0 + by0 = 1)
即位
x = x0 + b * t ,和 y = y0 - a * t
(就暴力更改至 [0 , x1] 和 [0 , y2] 的合法区间即可)
就可以求解另一个值。
这种解法求出来了,问题的关键就是等式的推导
还有一个关于数字的分析找规律,可以参考博客学习
题解中还有种取模的推导方法,感觉比较好,学习一下思路想法
上面的几种方法就是将一下各种数论知识的熟练运用,看一看学习一下
具体代码实现有两个写法
1.拓展欧几的推导方法
#include<stdio.h>
typedef long long ll;
void exgcd(ll a,ll b,ll &x,ll &y,ll &d)
{
if(!b){
x = 1;y = 0;d = a;
}
else{
exgcd(b,a%b,y,x,d);
y -= x*(a/b);
}
}
int main()
{
ll a,b,x,y,d;
scanf("%lld %lld",&a,&b);
exgcd(a,b,x,y,d);
while(x < 0){
x += b;
}
while(y < 0){
y += a;
}
printf("%lld",a*(x-1)+b*(y-1)-1);
return 0;
}
2.赛瓦维斯特定理:C = a * b - a - b 中,表示不存在非负整数解的最大整数
#include<stdio.h>//赛瓦维斯特定理:https://www.cnblogs.com/xxzh/p/9178564.html
int main()
{
long long a,b;
scanf("%lld %lld",&a,&b);
printf("%lld",a*b-a-b);
return 0;
}