poj 3181 dp+高精度(数字拆分)

题意:给定两个数n和k,问将n用1到k这k个数字进行拆分,有多少种拆分方法。例如:n=5,k=3 则有n=3+2,n=3+1+1,n=2+1+1+1,n=2+2+1,n=1+1+1+1+1共5种拆分方法

思路:dp[i][j]表示数字n的拆分序列中最大的数字为 j 的拆分方法。那么每次求dp[i][j]的时候对序列中有几个j进行枚举即可。此题需要注意的是高精度的处理,用long long不够存,那么考虑用两个long long 分别存结果的前一部分和后一部分。实际上判断最终结果有多大恐怕还得是先用数组模拟高精度测试一下大数据有多大才行。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define N 1005
struct node{
    long long a,b;
}dp[N][1005],one;
int n,m;
long long inf;
struct node solve(int n,int m){
    struct node tmp;
    if(n<m)
        return solve(n, n);
    if(m==1 || n==0)
        return one;
    if(dp[n][m].a||dp[n][m].b)
        return dp[n][m];
    for(int i = 1;i*m<=n;i++){
        tmp = solve(n-i*m, m-1);
        dp[n][m].a+=(tmp.a+(tmp.b+dp[n][m].b)/inf);
        dp[n][m].b=(dp[n][m].b+tmp.b)%inf;
    }
    tmp = solve(n, m-1);
    dp[n][m].a+=(tmp.a+(tmp.b+dp[n][m].b)/inf);
    dp[n][m].b=(dp[n][m].b+tmp.b)%inf;
    return dp[n][m];
}
int main(){
    int i,j;
    for(i = 0,inf=1;i<18;i++)
        inf *= 10;
    one.a = 0;
    one.b = 1;
    scanf("%d %d",&n,&m);
    for(i = 0;i<=n;i++)
        for(j = 0;j<=m;j++)
            dp[i][j].a = dp[i][j].b = 0;
    solve(n,m);
    if(dp[n][m].a)
        printf("%lld",dp[n][m].a);
    printf("%lld\n",dp[n][m].b);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值