如题:http://poj.org/problem?id=3181
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 4850 | Accepted: 1846 |
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$1Write 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
Source
思路:dp[i][j]表示i任意划分,最大的数也不超过j的划分数。
dp[i][j]=∑(k=0,i/j) dp[i-k*j][j-1] 相当于从i中取出任意个j,剩下的最大的数不超过j-1。
注意到dp[i][j]由两种状态推出,一种是最大值小于j,一种是最大值等于j。
因此优化递推关系得:
dp[i][j]=dp[i][j-1]+dp[i-j][j]。
数据量很大,连long long 都会超,因此使用高精度。
dp[i][j]:保存的是当前(i,j)状态的进位。
t[i][j]:保存的是取模的余数。(64位int为19位)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long dp[1005][105],t[1005][105],MOD;
int main()
{
int n,m;
cin>>n>>m;
int i,j;
for(i=0;i<=m;i++)
{
t[0][i]=1;
}
MOD=1;
for(i=0;i<18;i++)
MOD=MOD*10;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(i>=j)
{
dp[i][j]=dp[i-j][j]+dp[i][j-1]+(t[i-j][j]+t[i][j-1])/MOD;
t[i][j]=(t[i-j][j]+t[i][j-1])%MOD;
}
else
{
dp[i][j]=dp[i][j-1];
t[i][j]=t[i][j-1];
}
if(dp[n][m])
printf("%I64d",dp[n][m]);
printf("%I64d\n",t[n][m]);
return 0;
}