分析
排序之后
可以证明,枚举最后无法凑出的数然后统计答案一定是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; }