[CEOI2015 Day2]世界冰球锦标赛

传送门

题目大意

给定 n n n 个正整数,从中选出若干个数,使得和不超过 m m m,问有多少种合法的方案。

Solution

乍一眼看一脸不可做,但是看到数据范围就豁然开朗了。

N ≤ 40 N\le40 N40

很显然是爆搜。Yes,brute force yyds.

好吧很快发现爆搜会炸,复杂度是 O ( 2 n ) O(2^n) O(2n),是过不了的。

然后我们一拍脑瓜,掏出一个折半搜索,然后就做完了。

先考虑爆搜前一半,复杂度是 O ( 2 20 ) O(2^{20}) O(220),非常可以。

然后总共最多也就 2 20 2^{20} 220 种结果,我们直接掏出一个数组把每个结果存下来。

然后排序。

然后再爆搜后一半,复杂度还是 O ( 2 20 ) O(2^{20}) O(220)。对于每一个结果,我们二分查找一下,就可以得到前一半中有多少个可以与之匹配了。

Code

#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
using namespace std;
const int MAXN=2e6+10;
ll a[45],lsh[MAXN],tot;
ll m;
int n,fft,lcnt;
void dfs1(int p,ll sum){
	if(sum>m) return;
	if(p>fft){
			lsh[++tot]=sum;
		return;
	}
	dfs1(p+1,sum);
	dfs1(p+1,sum+a[p]);
}
ll ans;
void dfs2(int p,ll sum){
	if(sum>m) return;
	if(p>n){
		ans+=upper_bound(lsh+1,lsh+1+tot,m-sum)-lsh-1;
		return;
	}
	dfs2(p+1,sum);
	dfs2(p+1,sum+a[p]);
}
int main()
{
	scanf("%d%lld",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	fft=n/2;
	dfs1(1,0);
	sort(lsh+1,lsh+1+tot);
	dfs2(fft+1,0);
	printf("%lld\n",ans);
}

End

校内模拟赛 T2,最水的一题,没有之一。

虽然我很丢脸地挂了 20 pts。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值