little w and Exchange 解析

little w and Exchange 解析

题目链接传送门

这是一道思维题,对于输出的n个数,如果这n个数可以任意组合相加成1~m的数,则输出YES。

没做出来,看了解析

解析就两句话:

定义有n张纸币,且存在m,使得这n张纸币可以通过任意组合构成不超过m元的任意值,则n符合
用a[n+1]表示第n+1张纸币的值,当a[n+1] <= m+1 时n+1才符合
证明:
反证法:若a[n+1] > m+1,那么无论n+1张纸币如何组合,都无法构成m+1元
注意:计算前要将a[n]进行从小到大排序

原谅我理解能力差,看的云里雾里

下面是我的证明

  • 对a数组排序。从小到大
  • 数学归纳法
  1. a[0]=1,a[0]~ a[0]能表示整数数列为1 ~ 1 (其中t=1,我们把这种从1到t的数列称作截尾)

  2. 对a[i],若a[0~i] 所能表示范围为 1 ~ t,则添上a[i+1]后所能表示的数列为【1,t】 ∪【a[i+1],a[i+1]+t】
    (a[i+1]不参与组合时继承上次的范围即【1,t】,也可只选择a[i+1]或在之前的每种组合里都加上a[i+1],此时数列为【a[i+1],a[i+1]+t】)

    当两个数列可以无缝拼接,即a[i+1]<=t+1时,所表示数列更新为【1,a[i+1]+t】,显然这是截尾
    若两个数列不能无缝拼接,即a[i+1]>t+1时,所表示数列更新为【1,t】∪【a[i+1],a[i+1]+t】
    (我们称这种中间有坑的数列为拖尾)
    那么如果出现拖尾会怎么样呢,我们在向下走一步看
    对于一个大于等于a[i+1]的数k,如果在a[i+1]后边加上k后,所表示的数列将更新为【1,t】∪【a[i+1],a[i+1]+t】∪【k等等】,因为k>=a[i+1]>t的,所以 k是不可能填补拖尾的坑的。
    也就是说当a[i+1]>t+1时即会出现拖尾,而拖尾的坑是不可能被大于a[i+1]的数填补的

综上所述,当a[0~i]所表示的连续数列为【1,t】时,若a[i+1]<=t+1,则数列拓展为【1,t+a[i+1]】
若a[i+1]>t+1时,将产生拖尾,而由于数组a排序过,后面的所有数都大于等于a[i+1],所以拖尾永远不可能被填补,连续的数列范围将会固定为【1,t】

代码如下

#include <iostream>
#include <algorithm>
#define maxn 1005
using namespace std;
int a[maxn];
int n,m;
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(a,a+n);
    int t=0;
    for(int i=0;i<n;i++){
        if(a[i]>t+1)break;
        else{
            t+=a[i];
        }
    }
    if(m<=t)cout<<"YES";
    else cout<<"NO";
    return 0;
}
	

结语

其实这是在看了大佬的答案后来解释的,
要是让我从无到有写出来这道题,我只能说呵呵了。
唉,大佬不愧是大佬,思维题不愧是思维题

发布了15 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/fuckguidao/article/details/104919583