·【蓝桥】·买不到的数目


title: ·【蓝桥】·买不到的数目
tags:

  • 蓝桥
  • 数论
  • 枚举
  • 动态规划

categories:

  • 题目

题目来源:买不到的数目
总结该题有三种解法:

问题描述
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数,表示每种包装中糖的颗数(都不多于1000)
输出格式
一个正整数,表示最大不能买到的糖数
样例输入1
4 7
样例输出1
17
样例输入2
3 5
样例输出2
7

数学知识

  • 典型的Ax+By=C问题(A、B及两个包装糖数量,C是总糖数),C未知情况下,讨论不定方程的解和C的取值的关系,我的另一篇博客上有详细总结:
    Ax+By=C的解的讨论(仅A,B为常数)

  • 该题求最大不能组合出的数字,也就是求导致Ax+By=C无解的C的最大值,于是可以得出一些隐含条件:
    ①方程存在无解,且无解的个数有限 ②考虑实际情况x、y均非负

  • 于是由数学知识得:
    所有输入样例均满足A、B互质,继而直接输出结果cout << A*B-(A+B)

枚举

如果不知道上面的数学知识,什么A、B互质的,本题可以通过枚举求解
算法思想

  • 既然导致不定方程无解的C有最大值max,那么可以确定一个C的上界MAX,然后枚举x和y,把小于这个上界MAX的可行解都枚举出来,最后从大往小的筛选即可。
  • 如何确定这个上界MAX? A和B既然都不大于1000,那就直接令MAX=A*B吧。
    —————————————————完整代码—————————————————
#include <iostream>
#include <set>

using namespace std;

int main(){
	set<int> c;
	int a, b;
	cin >> a>> b;
	for(int x = 0; a*x <= a*b; ++x){//上限a*b
		for(int y = 0; a*x+b*y <= a*b; ++y){
			c.insert(a*x+b*y);//用set将可行的c都枚举出来
		}
	}
	for(int k = a*b; k >= 0; --k){//从大往小的筛选,找第一个不存在
		if(c.find(k) == c.end()){
			cout << k <<endl;
			break;
		}
	}
	return 0;
}

动态规划

动态规划又是对上面枚举的高度总结:

  • 数组dp的长度沿用了上界MAX;
  • dp[i]为1,表示C取i是有解,反之为0,无解;
  • 直接上dp方程吧:dp[i] = (dp[i-a]||dp[i-b]) ? 1 : 0

————————————————完整代码—————————————————

#include <iostream>
#include <algorithm>

using namespace std;

int dp[1000005];
int main(){
	int a, b;
	cin >> a >> b;
	dp[a] = 1; dp[b] = 1;
	for(int i = max(a, b)+1; i < a*b; ++i){
		dp[i] = (dp[i-a] || dp[i-b]);
	}
	for(int i = a*b-1; i > 0; --i){//同样从大往小的筛选,找第一个为0的
		if(!dp[i]){
			cout << i << endl;
			break;
		}
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/weayer/p/13184598.html