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

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

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

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

 

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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
const int maxn=1005;
long long dp[maxn][41];  //增加一维存储每一位的数
int n,k;
int main() {

    while(scanf("%d%d",&n,&k)!=EOF) {
        memset(dp,0,sizeof(dp));
        dp[0][1]=1;
        for(int i=1; i<=k; i++) {
            for(int j=i; j<maxn; j++) {
                //原本就直接写了dp[j]+=dp[j-i],不WA才怪了。。。
                for(int z=1;z<40;z++){
                    dp[j][z]=dp[j][z]+dp[j-i][z];
                    if(dp[j][z]>9){
                        dp[j][z]-=10;
                        dp[j][z+1]++;
                    }
                }
            }
        }
        int idx=40;
        while(dp[n][idx]==0)
            idx--;
        for(int i=idx;i>=1;i--)
            printf("%d",dp[n][i]);
        printf("\n");
    }
    return 0;
}

 

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

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
const long long mod=10000000000000000;
const int maxn=1005;
long long dphigh[maxn];  //一个数的高位部分
long long dplow[maxn];   //一个数的低位部分
int n,k;
int main() {

    while(scanf("%d%d",&n,&k)!=EOF) {
        memset(dphigh,0,sizeof(dphigh));
        memset(dplow,0,sizeof(dplow));
        dplow[0]=1;
        for(int i=1; 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 0;
}

 

 

posted @ 2013-12-08 16:27  辰曦~文若  阅读(246)  评论(0编辑  收藏  举报