题意:有n个硬币,价值总和为m,问硬币可以凑成1 ~ m的所有价值 的方案总数为多少
思路:dp题,设dp[i][j][k]表示:用i个硬币能凑成1 ~ j且最大面值为k的方案数,那么增加一个面值为add(add >= k)的硬币时, 则有dp[i + 1][j + add][add] += dp[i][j][k],注意add的值不能超过j + 1,理由是当add > j + 1时,无论怎样都凑不出j + 1, j + 2 .... add - 1的价值
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long ll;
const ll mod = 2 * 1e9 + 7;
const int maxn = 210;
using namespace std;
int T, n, m;
ll dp[maxn][maxn][maxn];
void init() {
memset(dp, 0, sizeof dp);
dp[1][1][1] = 1;
for(int i = 1; i <= 199; i++) {
for(int j = 1; j <= 200; j++) {
for(int k = 1; k <= 200; k++) {
if(!dp[i][j][k]) continue;
for(int add = k; add + j <= 200 && add < j + 2; add++) {
dp[i + 1][j + add][add] += dp[i][j][k];
dp[i + 1][j + add][add] %= mod;
}
}
}
}
}
int main() {
init();
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &m);
ll ans = 0;
for(int i = 1; i <= m; i++) {
ans = (ans + dp[n][m][i]) % mod;
}
printf("%lld\n", ans);
}
return 0;
}