题目大意:完全背包
思路 : dp[i+1][j] = dp[i][j] + dp[i][j-i]
注意:会爆long long,要用两个long long 数组,一个存储高位,另一个存储低位
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const long long M = 1000000000000000;
int main()
{
int n,k;
long long dp[110][1010],a[110][1010];
while(~scanf("%d%d", &n, &k))//n元钱,k种硬币
{
memset(dp, 0, sizeof dp);
memset(a, 0, sizeof a);
dp[1][0] = 1;//表示前1种钱币前的0种钱币凑成0元只有一种可能
for(int i = 1; i <= k; i++)
for(int j = 0; j <= n; j++)
if(j >= i)
{
dp[i+1][j] = (dp[i][j] + dp[i+1][j-i])%M;
a[i+1][j] = a[i][j] + a[i+1][j-i] + (dp[i][j] + dp[i+1][j-i])/M;
}
else
{
dp[i+1][j] = dp[i][j];
a[i+1][j] = a[i][j] + (dp[i][j])/M;
}
if(a[k][n])
printf("%lld%015lld\n", a[k+1][n], dp[k+1][n]);
else
printf("%lld\n",dp[k+1][n]);
}
return 0;
}
/*
1.前面i种硬币已经凑成j元 dp[i][j]
2.前面i种硬币凑成j-k*i元 加上k*i凑成j
*/