【洛谷 3951】【NOIP2017 提高组D1T1】 小凯的疑惑【数学】

102 篇文章 0 订阅
10 篇文章 0 订阅

题目描述
小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。每种金币小凯都有 无数个。在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。现在小 凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在 小凯无法准确支付的商品。


输入格式
两个正整数 a 和 b,它们之间用一个空格隔开,表示小凯中金币的面值。

输出格式
一个正整数 N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。


输入输出样例
输入 #1
3 7
输出 #1
11


说明/提示
【输入输出样例 1 说明】
小凯手中有面值为 3 3 3和$ 7 7 7的金币无数个,在不找零的前提下无法准确支付价值为 1 , 2 , 4 , 5 , 8 , 11 1, 2,4,5,8,11 1,2,4,5,8,11 的物品,其中最贵的物品价值为 11 11 11,比 11 11 11 贵的物品都能买到,比如:

12 = 3 × 4 + 7 × 0 12=3×4+7×0 12=3×4+7×0

13 = 3 × 2 + 7 × 1 13=3×2+7×1 13=3×2+7×1

14 = 3 × 0 + 7 × 2 14=3×0+7×2 14=3×0+7×2

15 = 3 × 5 + 7 × 0 15=3×5+7×0 15=3×5+7×0

【数据范围与约定】

对于 30 30 30%的数据: 1 ≤ a , b ≤ 50 1≤a,b≤50 1a,b50

对于 60 60 60%的数据: 1 ≤ a , b ≤ 1 0 4 1≤a,b≤10^4 1a,b104

对于 100 100 100%的数据: 1 ≤ a , b ≤ 1 0 9 1≤a,b≤10^9 1a,b109


解题思路
法一:

  • 有两种金额的金币: a , b a,b a,b
    不妨设 a < b a < b a<b,令答案为 x x x
    x = m a + n b ( 1 ≤ m ≤ b − 1 ) x=ma+nb(1≤m≤b−1) x=ma+nb(1mb1)
    显然当 n ≥ 0 n≥0 n0时 x 可以用 a , b a, b a,b表示出来,不合题意。
    因此当 n = − 1 n = -1 n=1 x x x 取得最大值,此时 x = m a − b x = ma - b x=mab
    显然当 m m m取得最大值 b − 1 b - 1 b1 x x x 最大,此时 x = ( b − 1 ) a − b = a b − a − b x=(b−1)a−b=ab−a−b x=(b1)ab=abab
    因此 a , b a, b a,b 所表示不出的最大的数是 a b − a − b ab - a - b abab

法二:

  • 第一种思路:
  1. a ∗ b a*b ab 一定可以被表示出来,表示为 a a a b b b b b b a a a。因为 a , b a,b a,b互质,没有其他表示出a*b的方法。
  2. 因为 a , b a,b a,b互质, a ∗ b − a a*b-a aba 不能被b表示出来,但可以被 a a a表示出来; b ∗ a − b b*a-b bab不能被a表示出来,但可以被 b b b表示出来。
  3. 因为 a , b a,b a,b互质,一个数如果不能被b表示出来,减去b以后还是不能被b表示出来;一个数如果不能被a表示出来,减去 a a a以后还是不能被 a a a表示出来;所以 a ∗ b a*b ab减去 a a a再减去b即可使两者都不能被表示出来。
  • 第二种思路
  1. 假设这个k它真的可以被表示为 m ∗ a + n ∗ b m*a+n*b ma+nb(玄学的思路)
  2. 在有关 a , b a,b a,b的条件不变的情况下,那m和n一定不是普通数。不然如何凑出一个原本凑不出来的数?原题中 m , n m,n m,n为正整数,为打破这一规则,不妨设 n n n为负整数。此时为了k最大, n = − 1 n=-1 n=1
  3. 代入 n = − 1 , k = m ∗ a − b n=-1,k=m*a-b n=1k=mab。由第一种思路的第二条, b ∗ a − b b*a-b bab能被b表示出来,为了让它不能被表示出来,又要m最大,所以 m = b − 1 m=b-1 m=b1
  4. 代入 m = b − 1 m=b-1 m=b1,原式的最大值就等于: a ∗ b − a − b a*b-a-b abab

代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
long long a,b;
int main(){
	scanf("%lld%lld",&a,&b);
	printf("%lld",a*b-a-b);
	//(好感动,居然只有两行代码(^-^)~~
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值