小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入:
两个正整数,表示每种包装中糖的颗数(都不多于1000)
要求输出:
一个正整数,表示最大不能买到的糖数
不需要考虑无解的情况
例如:
用户输入:
4 7
程序应该输出:
17
再例如:
用户输入:
3 5
程序应该输出:
7
思路一:
数论
利用了pei’shu
如果a,b均是正整数且互质,那么由 ax+by,x≥0,y≥0不能凑出的最大数是(a−1)(b−1)−1
引理:给定a,b,若gcd(a,b)>1,则一定不能凑出最大数
利用了裴蜀定理。
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n, m;
cin >> n >> m;
cout << (n-1) * (m-1) - 1 << endl;
return 0;
}
思路二:
dp
用bool数组dp[i]表示能否组合成i,将dp[0],dp[n]和dp[m]都置为1
for循环遍历,每遍历到一个数,都要看看dp[i - n]或dp[i -m]是否为1,如果是,则置true,否则就更新ans
从n和m中较大的数开始遍历,遍历到nm即可,因为我们已经将dp[0],dp[n]和dp[m]都置为1,且易得比nm大的数必定可以被n,m组合
ans就是指最大不能买的数目,循环结束,便可直接输出ans
具体操作见代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
bool dp[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n, m, ans;
cin >> n >> m;
dp[0] = 1;
dp[n] = dp[m] = 1;
int maxn = max(n, m);
for(int i = maxn; i < n * m; i ++ ){
if(dp[i-n] || dp[i-m])
dp[i] = 1;
else
ans = i;
}
cout << ans << endl;
return 0;
}
转载于作者文章