Time Limit: 1000MS |
|
Memory Limit: 65536K |
Total Submissions: 5342 |
|
Accepted: 2025 |
Description
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
Output
Sample Input
5 3
Sample Output
5
题意:有n元钱,商品的价格在1~k元(每种价格的商品数量无限),用n元去买这些商品,最多有多少种选择。
题解:很明显的完全背包啦,不过当n为1000,k=100时,结果为32整数,超过了long long。 有两种解决方法:
1.直接在dp方程相加转化时模拟大数加法,个人就是这么写的
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int dp[1010][100]; int add(int a[],int b[]) { int k; for(k=0;k<100;++k) { b[k]+=a[k]; if(b[k]>9) { b[k+1]++; b[k]-=10; } } return *b; } int main() { int n,i,j,k; while(scanf("%d%d",&n,&k)!=EOF) { memset(dp,0,sizeof(dp)); dp[0][0]=1; for(i=1;i<=k;++i) { for(j=i;j<=n;++j) *dp[j]=add(dp[j-i],dp[j]); } for(i=100;i>0;--i) if(dp[n][i]) break; for(;i>=0;i--) printf("%d",dp[n][i]); printf("\n"); } return 0; }
2,这种方法是膜大神得来的,用两个long long数组拼接来表示超过long long的数据,long long为19位整数,注意输出和进位。
代码如下:
#include<cstdio> #include<cstring> #define ll __int64 ll INF=1000000000000000000; ll a[1010];//高位 ll b[1010];//低位 int main() { int n,k,i,j; while(scanf("%d%d",&n,&k)!=EOF) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); b[0]=1; for(i=1;i<=k;++i) { for(j=i;j<=n;++j) { a[j]=a[j]+a[j-i]+(b[j]+b[j-i])/INF; b[j]=(b[j]+b[j-i])%INF; } } if(a[n]==0) printf("%I64d\n",b[n]); else printf("%I64d%018I64d\n",a[n],b[n]); } return 0; }