【2019/03/02测试T1】锁

【题目】

传送门

题目描述:

Z 住的房子一共有 n n n 个人,他们每人有一个重要度。

房子的门上可以装若干把锁。

假设共有 k k k 把锁,命名为 1 1 1 k k k。每把锁有一种对应的钥匙,也用 1 1 1 k k k 表示。

钥匙可以复制若干份并发给任意多个居民。每个人都可以持有若干钥匙,可以不持有钥匙。

如果几名居民钥匙的并集是全集,他们都在场时就能打开房门。

房东规定,一组居民都在场时能打开房门当且仅当他们的重要度加起来至少为 m m m

问至少需要给房间装多少把锁。即,求最小的 k k k,使得可以适当地给居民们每人若干钥匙,使得任意一组重要度之和小于 m m m 的居民持有的钥匙不能打开所有房门,使得任意一组重要度之和大于等于 m m m 的居民持有的钥匙能打开所有房门。

输入格式:

第一行两个整数 n n n m m m

第二行 n n n 个整数表示居民们的重要度 a i a_i ai

输出格式:

一个整数表示最少需要多少把锁,即最小的 k k k

样例数据:

输入
4 3
1 1 1 1

输出
6

提示:

对于前 30 % 30\% 30% 的测试数据,满足所有 a i = 1 a_i=1 ai=1
对于另外 30 % 30\% 30% 的测试数据, 1 ≤ n ≤ 8 1≤n≤8 1n8
对于 100 % 100\% 100% 的测试数据, 1 ≤ n ≤ 20 1≤n≤20 1n20 1 ≤ m ≤ 1 0 9 1≤m≤10^9 1m109,任意居民重要度 ≤ m ≤m m


【分析】

先细细地读一下题吧,考试的时候我看了好久才明白题目意思。

搞懂意思后,完全不知道怎么做,然后手动打表( a i = 1 a_i=1 ai=1),发现这个时候是杨辉三角,然后就有了 30 30 30 分。

至于为什么是杨辉三角,别问我,我不知道。

然后考完后看正解,发现这是一道结论题。题解如下:

答案就是重要度的和不足 m m m,但加入任何一个新居民都将导致重要度的和大于等于 m m m 的居民子集个数,将答案设为 x x x

下面就是证明为什么这样就是对的。

必要性:由于当前所有的集合重要度都不够 m m m,所以他们都至少缺一把锁。若不足 x x x 把锁,根据抽屉原理,必有两个子集 s 1 s_1 s1 s 2 s_2 s2 缺同一把锁 k k k。把这两个子集 s 1 s_1 s1 s 2 s_2 s2 并起来,仍然缺 k k k 这把锁,无法开门,但现在子集的重要度已经达到 m m m 了,与题目要求矛盾。

充分性:一共 x x x 把锁,每把锁上面各写一个这种居民的子集(互不相同)。一个居民持有所有上面的子集不包括自己的锁的钥匙,这样满足要求。

注意到如果所有人加起来重要度都不够 m m m,则需要一把锁,无人有钥匙。

其实那个充分性我没有看懂,不过我觉得看了必要性就可以理解这道题了吧。


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 25
using namespace std;
int a[N];
int main()
{
	int n,m,i,j;
	long long sum=0;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	if(sum<m){puts("1");return 0;}
	int ans=0,status=(1<<n);
	for(i=0;i<status;++i)
	{
		int Min=1e9+5;
		long long num=0;
		for(j=0;j<n;++j)
		{
			if(i&(1<<j))  num+=a[j+1];
			else  Min=min(Min,a[j+1]);
		}
		if(num<m&&num+Min>=m)  ans++;
	}
	printf("%d",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值