zoukankan      html  css  js  c++  java
  • AT2346 No Need

    atcoder上的题目

    链接

    一道思维题目

    可以发现如果X是可有可无的,那么所有小于X的数也一定是可有可无的,

    所有我们只要找出最大的那个可有可无的数字就好了

    进一步分析,发现

    若A1, A2, . . . , Ai 的和为 S,当且紧当 Ai+1, Ai+2, . . . , AN 凑不出任何个 K − S 到 K − 1 之 间的数字, A1, A2, . . . , Ai 都是可有可无的。

    我们来不太严谨的证明一下

    若A1, A2, . . . , Ai 的和为 S,如果 Ai+1, Ai+2, . . . , AN 凑不出任何个 K − S 到 K − 1 之 间的数字,那么 A1, A2, . . . , Ai 都是可有可无的。

    这显然是成立的

    当sum=Ai+1, Ai+2, . . . , AN 凑出任何个 K − S 到 K − 1 之 间的数字时,我们一定有sum+s>=K

    我们从小到大将sum+s减去Ai,一定会有一个j使得sum+s<k那么Aj就一定不是可有可无的

    我们将A从小到大排序

    01背包就好了

    一个小技巧,0一定是可有可无的,所以循环到0是一定会输出,可以适当代码更加优美

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<algorithm>
    # include<cstring>
    using namespace std;
    const int mn = 5005;
    int a[mn];
    bool vis[mn];
    int n,k,s;
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
          scanf("%d",&a[i]);
          a[i]=min(a[i],k);
          s+=a[i];
        }
        sort(a+1,a+1+n);
        vis[0]=1;
        for(int i=n;i>=0;i--)
        {
            bool flag=false;
            for(int j=k-1;j>=k-s && j>=0;j--)
               if(vis[j]) {
               flag=true;
               break;
               }
            if(!flag) 
            {
                printf("%d",i);
                return 0;
            }
            for(int j=k;j>=a[i];j--)
               vis[j]=(vis[j] | vis[j-a[i]]);
            s-=a[i];
        }
        return 0;
    }
  • 相关阅读:
    fafu 1231 dp(线段树优化dp)
    OUTLOOK+VBA 备份邮件到GMAIL
    心灵的程序:佛学与计算机
    建议增加编辑器插件“自动排版”
    高效演讲:简单四步走
    找呀找呀找地铁
    为什么你总是烦?
    变形金刚之雷曼疯狂兔子:抽水马桶变身
    客观:别人的主观
    用VBSCRIPT朗读文本
  • 原文地址:https://www.cnblogs.com/logeadd/p/9295477.html
Copyright © 2011-2022 走看看