zoukankan      html  css  js  c++  java
  • 牛客练习赛34 D little w and Exchange(归纳)

    题意:

    给n个数,和m

    问这组数是否可以构成[1, m]中的每一个数

    思路:

    先将a数组排序。

    先算算构成前几个数需要什么,至少需要a[1]=1

    需要a[2] = 1,2

    在a[2] = 1的情况下a[3] = 1, 2, 3, 在a[2] = 2的情况下a[3] = 1, 2, 3, 4 (不能等于5及以上,否则无法构成4)

    然后我们想决定a[4]的选择取决于什么,设s = a[1] + a[2] + a[3], 意味着前3个最多可以构成s

    同时还意味着前三个可以构成[1, s],

    因为a[4] >= a[3],这是我们排序的前提,

    若我们取a[4] = a[3],此时前四个可以构成[1, s + a[3]],

    (s+1到s+a[3]-1的值方法: 设要构成的数为x,先选全部的数,值为s+a[3],然后去掉s+a[3]-x,去掉的这个数范围为[1, a[3] - 1],这个范围在[1, s]之内,可以在之前的3个数中选)

    所以这个a[3]就是下限了!

    我们再想想刚才那个判断下限的过程,一个特殊点在于区间[1, a[3] - 1]包含于[1, s]

    前者与a[4]的选择有关!!!

    前者实际上就是[1, a[4]], 为了满足上述区间包含的关系,a[4]最多可以为s+1!

    所以a[4]的取值范围就是[a[3], s + 1]

    不只是a[4],我们上述过程其实呈现了一个归纳的过程,上述结论可以扩展到

    对于满足题意的有序数组a,设$displaystyle s = sum_{j=1}^i a[j]$,一定有$displaystyle a[i] leq a[i+1] leq s+1$

    检查满不满足即可

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int a[1000 + 10];
    int main(){
        int n, m;
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        sort(a+1, a+1+n);
        int tmp = 0;
        for(int i = 1; i <= n; i++){
            if(a[i] <= tmp+1){
                tmp += a[i];
            }
            else break;
        }
        if(tmp >= m)printf("YES");
        else printf("NO");
        return 0;
    }
  • 相关阅读:
    2.六角星绘制
    1.五角星绘制
    Redis
    javaScript
    反射
    区分'方法'和'函数'
    递归,二分法
    匿名函数,排序函数,过滤函数,映射函数,
    生成器,生成器函数,推导式,生成器表达式.
    函数,闭包,迭代器
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10134578.html
Copyright © 2011-2022 走看看