『蓝桥杯省赛』买不到的数目——扩展欧几里得算法

历届试题 买不到的数目  

时间限制:1.0s   内存限制:256.0MB

问题描述

小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。

小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。

你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。

本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。

输入格式

两个正整数,表示每种包装中糖的颗数(都不多于1000)

输出格式

一个正整数,表示最大不能买到的糖数

样例输入1

4 7

样例输出1

17

样例输入2

3 5

样例输出2

7

『解题思路』


这道题只要了解一些基础数论的同学,应该都会很直接想到扩展欧几里得算法:

对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然

存在整数对 x,y ,使得 gcd(a,b)=ax+by。

根据这个原理就可以得到一个结论:不能表示为  形如 x*a+y*b   x>=0 ,y>=0 的最大的整数是 a*b-a-b。(a>1,b>1 a,b互质)。

下面给出证明(过程来自:https://blog.csdn.net/jingqi814/article/details/21734449

 1 首先证明,关于x,y的不定方程:  x*a+y*b=a*b-a-b    无非负整数解

反设这个方程有解,变形一下,x*a+(y+1)*b=a*b-a  ,则推出a|(y+1)*b (|是整除符号),

那么由于(a,b)=1  ,推出, a|y+1 ,由于y+1!=0, 这样y+1>=a

带回原方程,x*a+(y+1)*b>=0*a+a*b>=ab>ab-a,   和原方程矛盾。

 

2  其次证明 如果n>ab-a-b  , 方程x*a+y*b=n 一定有非负整数解。

只需证明:

取l>=1   证明a*b-a-b+l =x*a+y*b 一定有非负整数解。

先考虑如下一个方程,x*a+y*b=l  (l,不是1),有裴蜀定理,这个方程一定有无穷多组整数解,取出一组解,不妨设  x0*a-y0*b=l      x0>=1 ,y0>=0;再使得y0满足y0<=a-1  

由于所有解里面y的取值是mod a 同余的,一定可以取到0~a-1这个范围里面)

 

取出来了这个x0,y0以后,带回方程a*b-a-b+l =x*a+y*b ,

则 a*b-a-b+l =a*b-a-b+(x0*a-y0*b)=(a-y0-1)*b+(x0-1) *a  , a,b的系数都是非负的了,所以解找到了。

综合1,2两步 ,ab-a-b 不可以被表示,大于ab-a-b的整数通通可以被表示。

『AC代码』


OJ的数据有点弱

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
    int a,b;
    cin>>a>>b;
    cout<<a*b-a-b<<"\n";
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
扩展欧几里得算法是求解一元一次不定方程 ax + by = gcd(a,b) 的一种方法,其中 a 和 b 是整,gcd(a,b) 是它们的最大公约,x 和 y 是整解。逆元是指在模运算下,一个的乘法逆元是指与它相乘后模运算得到 1 的。在论中,常常需要求一个在模意义下的逆元,即一个 k 满足 (k * x) % m = 1,其中 m 是模。 下面是扩展欧几里得算法求逆元的 C 语言实现: ```c #include <stdio.h> // 扩展欧几里得算法 int exgcd(int a, int b, int *x, int *y) { if (b == 0) { *x = 1; *y = 0; return a; } int gcd = exgcd(b, a % b, y, x); *y -= a / b * (*x); return gcd; } // 求逆元 int modinv(int a, int m) { int x, y; int gcd = exgcd(a, m, &x, &y); if (gcd != 1) { return -1; // a 和 m 不互质,不存在逆元 } else { return (x % m + m) % m; // 转化为正整 } } int main() { int a = 3, m = 11; int inv = modinv(a, m); if (inv == -1) { printf("%d 在模 %d 意义下不存在逆元\n", a, m); } else { printf("%d 在模 %d 意义下的逆元是 %d\n", a, m, inv); } return 0; } ``` 这个程序中,exgcd 函通过递归实现扩展欧几里得算法,返回 a 和 b 的最大公约,并且求出 x 和 y 的值。在 modinv 函中,我们调用 exgcd 函求出 a 和 m 的最大公约,并且判断 a 和 m 是否互质,如果不互质则不存在逆元。否则,根据扩展欧几里得算法的结果,求出 x 的值作为 a 在模 m 意义下的逆元。注意,由于 x 可能是负,所以要将其转化为正整
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值