分析
排序之后
可以证明,枚举最后无法凑出的数然后统计答案一定是OK的
比它值小的必须选
所以可以直接暴力背包
背出方案数暴力加上答案即可
时间复杂度:
代码
//Newcoder 18 D
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define LL long long
#define Lowbit(X) (X&(-X))
#define Lson (X<<1)
#define Rson (X<<1|1)
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(LL i=A;i<=B;i++)
#define BOR(i,A,B) for(LL i=A;i>=B;i--)
#define FOR_SIDE(i,A) for(LL i=Head[A];i;i=Next[i])
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const LL MAXN=3e4+10;
LL DP[MAXN],Num[MAXN],Total,Limit,Ans,Sum;
LL Pre[MAXN];
inline void File() {
freopen(".in","r",stdin);
freopen(".out","w",stdout);
}
signed main() {
//File();
scanf("%lld %lld",&Total,&Limit);
FOR(i,1,Total) { scanf("%lld",&Num[i]); }
sort(Num+1,Num+Total+1);
FOR(i,1,Total) Pre[i]=Pre[i-1]+Num[i];
FOR(i,1,Total) {
if(Limit-Pre[i-1]<0) break;
Cl(DP,0);
DP[0]=1;
Limit-=Pre[i-1];
FOR(j,i+1,Total) {
BOR(k,Limit,Num[j])
DP[k]+=DP[k-Num[j]];
}
FOR(j,max((LL)0,Limit-Num[i]+1),Limit) Ans+=DP[j];
Limit+=Pre[i-1];
}
printf("%lld\n",Ans);
//fclose(stdin); fclose(stdout);
// system("pause");
return 0;
} 
京公网安备 11010502036488号