POJ 3181 Dollar Dayz DP

2014-11-24 09:48:34 · 作者: · 浏览: 0

题目大意:

给你n元钱和无限个价钱为1~k的物品,让你求有多少种方法花光这n元钱?

思路:

参考别人的。。

可以看成是整数的划分。

如5 3

1+1+1+1+1

1+1+1+2 1+2+2

1+1+3 2+3

设dp[i][j]为i的划分中最大数不超过j的划分总数。

则dp[i][j]=dp[i][j-1]+dp[i-j][j];

有点像组合的某个公式。

最大数不选j即最大数为J-1的个数+最大数选中了j,即dp[i-j][j]。

值得一提的是结果可能会很大,看到大神的思路是这样的,用两个__int64的整数来模拟高精度。

把一个数拆成两个。

Orz。。

#include
  
   
#include
   
     const int MAXN=1000+10; __int64 a[MAXN][MAXN],b[MAXN][MAXN],mod=1; //dp[i][j]为i的划分中最大数为j的数目 int main() { int n,k; for(int i=1;i<=18;i++) mod*=10; while(~scanf(%d%d,&n,&k)) { memset(b,0,sizeof(b)); memset(a,0,sizeof(a)); for(int i=0;i<=k;i++) a[0][i]=1; for(int i=1;i<=n;i++) { for(int j=1;j<=k;j++) { if(i >= j ) { a[i][j]=(a[i][j-1] + a[i-j][j])%mod; //后面的位数 b[i][j]=b[i][j-1]+b[i-j][j] +(a[i][j-1] + a[i-j][j])/mod;//前面的位数 } else { a[i][j]=a[i][j-1]; b[i][j]=b[i][j-1]; } } } if(b[n][k]) printf(%I64d,b[n][k]); printf(%I64d ,a[n][k]); } return 0; }