#include using namespace std; const int N = 1010, MOD = 1e9 + 7; int f[N][N], g[N][N]; // f[j]、g[j]分别表示体积最大为j时的最大价值、方案数 int main() { int n, m; scanf("%d %d", &n, &m); // 初始化,两个二维表,第一列比较特殊,可以进行初始化 // f[0][0],g[0][0] // 在前0个物品中选择,空间最多为0,只能什么也不选择,最大值f[0][0]=0,方案数:g[0][0]=1 f[0][0] = 0, g[0][0] = 1; // f[0][1~m],g[0][1~m] // 在前0个物品中选择,空间最多为1~m,最大值肯定是0,因为没的选择嘛,对应的方案数也是1 for (int i = 1; i <= m; i++) f[0][i] = 0, g[0][i] = 1; // 从第二列开始吧 for (int i = 1; i <= n; i++) { // 枚举每个物品,理解为阶段 int v, w; scanf("%d %d", &v, &w); for (int j = 0; j <= m; j++) { // 枚举当前阶段可能的剩余体积 int val = f[i - 1][j]; // 在没选择当前物品前的最大价值 if (j >= v) { // 如果剩余体积可以装得下第i个阶段的物品,选择与否可能会影响最大价值 if (val > f[i - 1][j - v] + w) { // 如果选择了当前物品还不如不选 f[i][j] = val; // 那还是用原来的最大价值吧 g[i][j] = g[i - 1][j]; // 个数也随着迁移吧 } else if (val == f[i - 1][j - v] + w) { // 如果一样的价值呢?那就需要累加了 f[i][j] = val; g[i][j] = (g[i - 1][j] + g[i - 1][j - v]) % MOD; } else { // 如果可以理新呢? f[i][j] = f[i - 1][j - v] + w; // 更新最大值 g[i][j] = g[i - 1][j - v]; // 同步更新方案数量 } } else { // 如果装不上,只能继承 f[i][j] = val; g[i][j] = g[i - 1][j]; } } } printf("%d\n", g[n][m]); return 0; }