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 = ;
int a[mn];
bool vis[mn];
int n,k,s;
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]=min(a[i],k);
s+=a[i];
}
sort(a+,a++n);
vis[]=;
for(int i=n;i>=;i--)
{
bool flag=false;
for(int j=k-;j>=k-s && j>=;j--)
if(vis[j]) {
flag=true;
break;
}
if(!flag)
{
printf("%d",i);
return ;
}
for(int j=k;j>=a[i];j--)
vis[j]=(vis[j] | vis[j-a[i]]);
s-=a[i];
}
return ;
}

最新文章

  1. SQL Server事务、视图和索引
  2. sqlalchemy中文乱码问题解决方案
  3. JAVA SSH 框架介绍
  4. VisualLeakDetector
  5. 【dynamic】简化反射简单尝试
  6. SEO 网站URL优化
  7. Winform 换皮肤
  8. MYSQL报Fatal error encountered during command execution.错误的解决方法
  9. HDU 4777 Rabbit Kingdom(树状数组)
  10. IE浏览器兼容
  11. 【技巧】datagrid锁定列后重新加载时出现错位问题的解决
  12. Solidity 中文文档 —— 第一章:Introduction to Smart Contracts
  13. ajax中的同步与异步修改数据的问题
  14. nativefier(一行代码将任意网页转化为桌面应用)
  15. Docker for windows 入门一(下载安装)
  16. 【转】Mysql学习---SQL的优化
  17. blockchain 名词解释
  18. Solr服务在Linux上的搭建详细教程
  19. Android -- SlidingMenu
  20. 求树的直径和中心(ZOJ3820)

热门文章

  1. 2019-10-11-VisualStudio-配置多进程调试快捷键启动项目
  2. ECMAScript 6 (浅显入门)
  3. Hibernate: insert into xxx (name) values (?)但是数据库中没有数据
  4. spring boot resttemplate发送post,get请求
  5. 稳定性专题 | StackOverFlowError 常见原因及解决方法
  6. 【python之路20】函数作为参数
  7. 【python之路14】发送邮件实例
  8. toString方法和valueof()方法的区别
  9. java如何访问memcache
  10. cronexpr任务调度