买不到的数目
小明开了一家糖果店。
他别出心裁:把水果糖包成4颗一包和7颗一包的两种。
糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。
当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。
大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数 n,m,表示每种包装中糖的颗数。
输出格式
一个正整数,表示最大不能买到的糖数。
数据范围
2≤n,m≤1000,保证数据一定有解。
输入样例:
4 7
输出样例:
17
前提条件:给定a,b,若d=gcd(a,b)>1(即最大公约数>1),则一定不能凑出最大数。
因为若d>1,则a和b一定是d的倍数,那么a和b凑出来的数也肯定是d的倍数,所以一定不会存在一个最大数,使得这个数之后的数字都能被a和b凑出来
结论: 如果 a,b均是正整数且互质,那么由 ax+by,x≥0,y≥0不能凑出的最大数是 (a−1)(b−1)−1(这是定理,证明很难,记住定理即可)。
互质:最大公约数为1
裴蜀定理:若a,b的最大公约数为d,怎一定存在两个整数p,q使得ap+bq=d,只要ab互质,则一定有解
若ab互质,则一定存在ap+bq=1,两边同时乘以m => apm+bqm=m => (am-q)p+(bm+p)q=m
方法1. 暴力搜索(打表找规律,会超时,AC50%)
当要凑的数字减到0的时候,说明凑出来了
先尝试用p来凑,要凑的数字变成m-p
再尝试用q来凑,要凑的数字变成m-q
如果都凑不出来,则返回false
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,ans;
bool dfs(int m,int p,int q){
if(!m) return true;
if(m>=p&&dfs(m-p,p,q)) return true;
if(m>=q&&dfs(m-q,p,q)) return true;
return false;
}
int main(){
cin>>n>>m;
for(int i=1;i<=1000;i++){
if(!dfs(i,n,m)) ans=i;
}
cout<<ans<<endl;
return 0;
}
根据这个暴力搜索我们可以打表找规律,如下:
3 2 1
3 4 5
3 5 7
3 7 11
3 8 13
大致可以发现规律为n=3时,m+1,ans+2
故ans=2m+x
代入数据得x=-3
推得公式为ans=2m-3;(n=3)
同理,多推几个公式
4 7 17
4 9 23
4 11 29
ans=3m-4(n=4)
最后整理得到大致公式ans=(n-1)*(m-1)-1.
方法2.利用公式直接输出答案:(p-1)(q-1)-1
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int main(){
cin>>n>>m;
cout<<(n-1)*(m-1)-1<<endl;
return 0;
}