蒟蒻这回是真的被一道水题卡住了

题目描述
椎名真白每天的午饭一直是各种各样的年轮面包。

她掏出了
n
n个年轮面包,第
i
i个年轮面包含有的热量为
w
i
w 
i
​
 。她可以选择吃掉其中一些,获得热量之和。

虽然椎名真白平时埋头画画对生活细节很不上心,但是对于自己的外貌身材还是十分在意的,她不想变得太胖或者太瘦,所以选择了一个热量获得区间
[
l
,
r
]
[l,r],每天中午从年轮面包获得热量必须在该区间内。

显然有多种选择方案能够满足条件,但是真白是个数学白痴,她想让你帮忙计算一下所有方案数。

输入格式
第一行输入
3
3个正整数
n
,
l
,
r
(
n
≤
40
,
1
≤
l
≤
r
≤
300
)
n,l,r(n≤40,1≤l≤r≤300)。

第二行输入
n
n个正整数,表示每份年轮面包含有的热量
w
i
(
20
≤
w
i
≤
100
)
w 
i
​
 (20≤w 
i
​
 ≤100)。

输出格式
一行一个整数,表示所有方案数。

样例
Input 1
4 70 85
80 75 90 70
Output 1
3
样例解释
对于样例输入,有以下
3
3种方案:

只吃第
1
1个面包
只吃第
2
2个面包
吃第
4
4个面包
每一种方案的热量之和都在
70
70到
85
85的范围内。

数据范围
n
≤
40
,
1
≤
l
≤
r
≤
300
,
20
≤
w
i
≤
100
n≤40,1≤l≤r≤300,20≤w 
i
​
 ≤100

WA10代码:

#include<bits/stdc++.h>
#define I using
#define AK namespace
#define IOI std
#define i_ak return
#define ioi  0
I AK IOI;
int n,l,r,a[45],ans;
void dfs(int sum,int now){
	if(sum>r)return;
	if(sum>=l)ans++;
	if(now==n)return;
	for(int j=now+1;j<=n;j++)dfs(sum+a[j],now+1);
}
int main(){
	cin>>n>>l>>r;
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(&a[1],&a[n+1],greater<int> ());
	dfs(0,0);
	cout<<ans;
	i_ak ioi;
}

@王建力 @2345安全卫士

@金杭东

if(now==n)return;

应该为

if(now==n+1)return;

要不然第n个就不会被选择了。

哦知道了不过为什么下面是

for(int j=now+1;j<=n;j++)dfs(sum+a[j],now+1);

不应该就是选和不选吗,这样复杂度会变高。
而且你这不对呀后面不应该是now+1而是j 呀要不然不就有被选两次的了吗

谢谢,AC了主要问题是把 j 写成 now+1

这个写成now==n 是因为这里的 n 记录的是已经用了几个数

你可以试着换种写法,就是对于每一个有选和不选,复杂度更低哦

好的,谢谢

@金杭东 对了,你知道怎么针对一道题目造出 hack 数据吗

找到错误代码,然后对拍

@金杭东 o,能帮我一下吗

这个和正确没有关系,他这个是优化时间的,所以打错了时间也只会时间超限,而剪枝够多所以过得去。

但是如果,应该是minv[i]+i*i*i他写成了minv[i-1]+i*i*i那就会错了

所以他不是故意打错的?是有意的?

就是打错了,如果改一下就跑得更快

o,所以剪枝够多可以避免微小错误

你仔细读代码,有些小错误不行的,他打这个也是为了剪枝打错了效率就低了点

好的,谢谢