AcWing 1205. 买不到的数目
题目描述
小明开了一家糖果店。
他别出心裁:把水果糖包成4颗一包和7颗一包的两种。
糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。
当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。
大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数 n,m,表示每种包装中糖的颗数。
输出格式
一个正整数,表示最大不能买到的糖数。
数据范围
2≤n,m≤1000,
保证数据一定有解。
输入样例:
4 7
输出样例:
17
题目分析–动态规划
题目寻找是两个数不能组成的数的最大值。
枚举所有的数,用数组f[i]表示数i是否可以被组合出来
f[i]=true表示i可以被n和m组合出来
当f[i-n]或者f[i-m]可以被表时则f[i]一定可以被表示
于是有状态转移: f[i] = f[i-n]||f[i-m]
什么时候终止呢?
设k = min(n, m),则当存在连续k个数均可以被表示时之后所有的数均可被表示
那么f数组应该开多大呢?
最多循环m*n次若仍然未找到答案则无解。
因为如果枚举到nm还是未找到答案的话,从nm开始又相当于从0开始枚举,进入死循环无解。
C++ 代码实现
#include <iostream>
using namespace std;
const int N = 1e6+10;
bool f[N];
int main() {
int n, m;
cin>>n>>m;
int cnt = 0;//记录连续可组成数的个数
int k = min(n, m);
f[0] = true;
int i = 2;
while(cnt < k) {
if(i >= n) f[i] = f[i-n];
if(i >= m) f[i] = f[i] || f[i-m];
if(f[i]) cnt++;
else cnt = 0;
i++;
}
//到达i已经存在连续k+1个可组成的数了
cout<<i-k-1<<endl;
return 0;
}
数论结论
最大数就是 (n-1)*(m-1)-1
证明过程可以参考这里
#include <iostream>
using namespace std;
int main() {
int n, m;
cin>>n>>m;
cout<<(n-1)*(m-1)-1<<endl;
return 0;
}