Dollar Dayz
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
求1到k中能够组合为n的最组合数
由于k的个数是无限制的,这和完全背包比较相似,因此就需要推一下dp的状态转移方程了,在这里定义一下dp[i][j]表示当前值为i的时候用1到j的组合数的最大值,我们很容易想到
1.dp[i][1]=1,还有就是当i<j的时候 dp[i][j]=dp[i][j-1];
2.当i>j的时候就需要思考一下,可以手动模拟前6个,就可以看出当推dp[i][j]的时候,dp[i][j]是由前j个数推出的,即dp[i][j-1],还有一部分,那就是dp[i-j][j],为什么?因为dp[i][j]也是在dp[i-j][j]的基础上加上jz所得出的,因此dp[i][j]=dp[i][j-1]+dp[i-j][j];
但是这样还是不能ac,因为这样di递推的话连long long都会越界,因此只能够用两个long long 类型的数组连接一下,这样就构成前19位,后19位了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll pre[1010][105];
ll back[1010][105];
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int main(){
int n,k;
ll M=1;
rep(i,1,18) M*=10;
scanf("%d%d",&n,&k);
rep(i,0,k)
back[0][i]=1;
rep(j,1,k)
{
rep(i,1,n)
{
if(j>i)
{
pre[i][j]=pre[i][j-1];back[i][j]=back[i][j-1];
}
else{
pre[i][j]=pre[i-j][j]+pre[i][j-1]+(back[i-j][j]+back[i][j-1])/M;
back[i][j]=(back[i-j][j]+back[i][j-1])%M;
}
}
}
if(pre[n][k]) printf("%I64d",pre[n][k]);
printf("%I64d\n",back[n][k]);
}
还可以优化
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll pre[1050];
ll back[1050];
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int main(){
int n,k;
ll M=1;
rep(i,1,18) M*=10;
scanf("%d%d",&n,&k);
back[0]=1;
rep(j,1,k )
{
rep(i,1,n)
{
if(j>i) continue;
else{
pre[i]=pre[i-j]+pre[i]+(back[i-j]+back[i])/M;
back[i]=(back[i-j]+back[i])%M;
}
}
}
if(pre[k]) printf("%I64d",pre[n]);
printf("%I64d\n",back[n]);
}