题目大意
小 \(T\) 要给他的妹妹买礼物~他会不断地买礼物,直到自己身上没有足够的钱来买任何一件礼物为止,他想知道有多少种方案符合他买礼物的方式。
请输出合法的方案。
解题思路
先不考虑限制,那么就是普通的 01
背包。
如果加上限制,那也是一样的思路,反过来看,"一直到没有足够的钱来买任何一件礼物为止"。
那么枚举没钱不能买的那个礼物,再跑 01
背包即可。
AC CODE
#include <bits/stdc++.h>
using namespace std;
#define int long long
namespace Fread
{
const int SIZE = 1 << 21;
char buf[SIZE], *S, *T;
char getchar()
{
if(S == T)
{
T = (S = buf) + fread(buf, 1, SIZE, stdin);
if(S == T) return '\n';
}
return *S++;
}
}
namespace Fwrite
{
const int SIZE = 1 << 21;
char buf[SIZE], *S = buf, *T = buf + SIZE;
void flush()
{
fwrite(buf, 1, S - buf, stdout);
S = buf;
}
void putchar(char c)
{
*S++ = c;
if(S == T) flush();
}
struct cxr
{
~cxr()
{
flush();
}
} boom;
}
int read()
{
int x = 0;
int T = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') T -= 2;
}
while(c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
return T * x;
}
void write(int x)
{
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int n, k;
int a[1007];
int f[1007];
int sum;
int ans;
const int mod = 1e7 + 7;
bool cmp(int a, int b)
{
return a > b;
}
signed main()
{
n = read();
k = read();
for(int i = 1; i <= n; ++i) a[i] = read(), sum += a[i];
sort(a + 1, a + n + 1, cmp);
if(k >= sum)
{
puts("1");
return 0;
}
f[0] = 1;
for(int i = 1; i <= n; ++i)
{
sum -= a[i];
for(int j = max(0ll, k - sum - a[i] + 1); j <= k - sum; ++j)
ans = (ans + f[j]) % mod;
for(int j = k; j >= a[i]; --j)
f[j] = (f[j] + f[j - a[i]]) % mod;
}
write(ans);
putchar('\n');
return 0;
}