Farmer John goes to Dollar Days at The Cow Store and discovers an unlimited number of tools on sale. During his first visit, the tools are selling variously for $1, $2, and $3. Farmer John has exactly $5 to spend. He can buy 5 tools at $1 each or 1 tool at $3 and an additional 1 tool at $2. Of course, there are other combinations for a total of 5 different ways FJ can spend all his money on tools. Here they are: 

        1 @ US$3 + 1 @ US$2

1 @ US$3 + 2 @ US$1
1 @ US$2 + 3 @ US$1
2 @ US$2 + 1 @ US$1
5 @ US$1
Write a program than will compute the number of ways FJ can spend N dollars (1 <= N <= 1000) at The Cow Store for tools on sale with a cost of $1..$K (1 <= K <= 100).

Input

A single line with two space-separated integers: N and K.

Output

A single line with a single integer that is the number of unique ways FJ can spend his money.

Sample Input

5 3

Sample Output

5


完全背包+高精度数

没有优化直接wa,是数值范围太小
#include<iostream>
using namespace std;
int dp[105][1005];
int main(){
    int n,k;
    cin>>n>>k;
    dp[0][0]=1;
    for(int i=1;i<=k;i++){
        for(int j=0;j<=n;j++){
            for(int k=0;k*i<=j;k++){
                dp[i][j]+=dp[i-1][j-k*i];
            }
        }
    }
    cout<<dp[k][n];
    return 0;
} 

 

 

 改用unsigned long long还是wa。那就用两个unsigned long long一个存低位一个存高位。unsigned long long的范围是1844674407370955161,所以用一个比它小一个数量级的数,

100000000000000000。
#include<iostream>
using namespace std;
unsigned long long dp[105][1005][2];
#define LIMIT_ULL 100000000000000000
int main(){
    int n,k;
    cin>>n>>k;
    dp[0][0][1]=1;//低位
    for(int i=1;i<=k;i++){
        for(int j=0;j<=n;j++){
            for(int k=0;k*i<=j;k++){
                dp[i][j][1]+=dp[i-1][j-k*i][1];
                dp[i][j][0]+=dp[i-1][j-k*i][0];
                dp[i][j][0]+=dp[i][j][1]/LIMIT_ULL;//低位的进位加到高位
                dp[i][j][1]=dp[i][j][1]%LIMIT_ULL;//低位去除进位
            }
        }
    }
    if(dp[k][n][0]){
        cout<<dp[k][n][0];
    }
    cout<<dp[k][n][1];
    return 0;
} 

 

以上比你不是最优的,可能会TLE

dp[i][j]+=dp[i-1][j-i*k]可以优化成dp[i][j]=dp[i-1][j]+dp[i-1][j-k]

因为当k>1时的计算结果,已经保存在了dp[i-1][j-k]

#include<iostream>
using namespace std;
unsigned long long dp[105][1005][2];
#define LIMIT_ULL 100000000000000000
int main(){
    int n,k;
    cin>>n>>k;
    dp[0][0][1]=1;
    for(int i=1;i<=k;i++){
        for(int j=0;j<=n;j++){
            if(j<i){
                dp[i][j][1]=dp[i-1][j][1];
                dp[i][j][0]=dp[i-1][j][0];
            }
            else{
                dp[i][j][1]=dp[i-1][j][1]+dp[i][j-i][1];
                dp[i][j][0]=dp[i-1][j][0]+dp[i][j-i][0];
                dp[i][j][0]+=dp[i][j][1]/LIMIT_ULL;
                dp[i][j][1]=dp[i][j][1]%LIMIT_ULL;
            }
        }
    }
    if(dp[k][n][0]){
        cout<<dp[k][n][0];
    }
    cout<<dp[k][n][1];
    return 0;
}