POJ 3181 Dollar Dayz (完全背包,大数据运算)

时间:2023-03-08 15:56:36

题意:给出两个数,n,m,问1~m中的数组成n,有多少种方法?

  这题其实就相当于 UVA 674 Coin Change,求解一样
  只不过数据很大,需要用到高精度运算。。。

后来还看了网上别人的解法,是将大数转化成高位和低位两部分处理

代码一:用数组存储数据的每个位

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std;
const int maxn=;
long long dp[maxn][]; //增加一维存储每一位的数
int n,k;
int main() { while(scanf("%d%d",&n,&k)!=EOF) {
memset(dp,,sizeof(dp));
dp[][]=;
for(int i=; i<=k; i++) {
for(int j=i; j<maxn; j++) {
//原本就直接写了dp[j]+=dp[j-i],不WA才怪了。。。
for(int z=;z<;z++){
dp[j][z]=dp[j][z]+dp[j-i][z];
if(dp[j][z]>){
dp[j][z]-=;
dp[j][z+]++;
}
}
}
}
int idx=;
while(dp[n][idx]==)
idx--;
for(int i=idx;i>=;i--)
printf("%d",dp[n][i]);
printf("\n");
}
return ;
}

代码二:将大数分成两部分,高位部分和低位部分

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std;
const long long mod=;
const int maxn=;
long long dphigh[maxn]; //一个数的高位部分
long long dplow[maxn]; //一个数的低位部分
int n,k;
int main() { while(scanf("%d%d",&n,&k)!=EOF) {
memset(dphigh,,sizeof(dphigh));
memset(dplow,,sizeof(dplow));
dplow[]=;
for(int i=; i<=k; i++) {
for(int j=i; j<maxn; j++) {
dphigh[j]+=dphigh[j-i];
dplow[j]+=dplow[j-i];
dphigh[j]+=(dplow[j])/mod;
dplow[j]=dplow[j]%mod;
}
}
if(dphigh[n])
printf("%I64d",dphigh[n]);
printf("%I64d\n",dplow[n]);
}
return ;
}