题意:给出两个数,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(" "); } 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 ",dplow[n]); } return 0; }