5184. 【NOIP2017提高组模拟6.29】Gift (Standard IO)
Time Limits:
1000 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSet
做法:设f[i][j]表示取i到n个物品,花费为j的方案数,统计答案时,假设此时无法选取的最小物品为x,除去必须要选的物品剩余Val,那么答案为f[x + 1][Val - c[x] + 1 ~ Val]
代码如下:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #define mo 10000007 6 #define LL long long 7 #define N 1007 8 using namespace std; 9 int n, m, a[N], Pre[N]; 10 LL f[N][N], ans; 11 12 int main() 13 { 14 scanf("%d%d", &n, &m); 15 for (int i = 1; i <= n; scanf("%d", &a[i++])); 16 sort(a + 1, a + n + 1); 17 for (int i = 1; i <= n; i++) 18 Pre[i] = Pre[i - 1] + a[i]; 19 if (Pre[n] <= m) 20 { 21 printf("1"); 22 return 0; 23 } 24 f[n + 1][m] = 1; 25 for (int i = n; i; i--) 26 { 27 for (int j = Pre[i - 1], k = min(m + 1, Pre[i - 1] + a[i]); j < k; j++) ans = (ans + f[i + 1][j]) % mo; 28 for (int j = m - a[i]; j >= 0; j--) 29 f[i][j] = (f[i][j] + f[i + 1][j] + f[i + 1][j + a[i]]) % mo; 30 for (int j = m; j >= m - a[i] + 1; j--) 31 f[i][j] = (f[i][j] + f[i + 1][j]) % mo; 32 } 33 printf("%lld", ans); 34 }