F - Ingenuous Cubrency ( UVa 11137 ,立方数之和,递推关系,算法进阶手册)

F - Ingenuous Cubrency

UVA - 11137

题目描述

​ 立方数之和。输入正整数n( n<=10000) ,求将n写成若干个正整数的立方和有多少种方法。

比如21有3种写法:21=13+13 …+13=23+13+13…13=23+23+13…13

77有22种写法,9999有440 022 018 293中写法。

多组输入

​ 每组输入一个n.

输出描述

​ 输出有多少种方法.

分析

​ 可以用多重背包写,也可以建立多段图(后者时间复杂度高),

多重背包

dp(i,j)表示最多不超过i,立方和为j的方法数目

初始状态:dp(0,0)=1

递推关系:dp (i,j)=dp(i-1,j)+dp(i,j - i*i*i*i ) (i>=1)

多段图:

初始状态:dp (0,0)=1

状态转移:对于每个dp(i,j) for k=0 to j+k*i*i*i<=maxn: dp(i,j+k*i*i*i)+=dp(i,j)

表示i,j这个状态可以加上一个i3 或者加上多个i3 转移到 i+1这个状态中

代码1:

#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#define mset(a,b)   memset(a,b,sizeof(a))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn=10000;
const int branch=26;
const int inf=0x3f3f3f3f;
const int MOD=1e6+7;
ll dp[26][maxn+10];
void Preprocess()
{
    mset(dp,0ll);
    dp[0][0]=1;
    for(int i=1; i<=21; ++i) //最大不超过i
    {
        for(int j=0; j<=maxn; ++j) //递推关系  实际从dp[i-1]行求dp[i]行
        {
            dp[i][j]=dp[i-1][j];
            if(j-i*i*i>=0)
              dp[i][j]+=dp[i][j-i*i*i];
        }
    }
}
int main()
{
    int n;
    Preprocess();
    while(~scanf("%d",&n))
    {
        cout<<dp[21][n]<<endl;
    }
}

代码2:

#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<iostream>
#include<iomanip>
#define mset(a,b)   memset(a,b,sizeof(a))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn=10000;
const int branch=26;
const int inf=0x3f3f3f3f;
const int MOD=1e6+7;
ll dp[26][maxn+10];
void Preprocess()
{
    mset(dp,0);
    dp[0][0]=1;
    for(int i=1; i<=21; ++i)
    {
        for(int j=0; j<=maxn; ++j) //从 i-1  j状态转移
        {
            for(int a=0; j+a*i*i*i<=maxn; ++a)
            {

                dp[i][j+a*i*i*i]+=dp[i-1][j];
            }
        }
    }
}
int main()
{
    int n;
    Preprocess();
    while(~scanf("%d",&n))
    {
        cout<<dp[21][n]<<endl;
    }
}

转载于:https://www.cnblogs.com/dchnzlh/p/10427284.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值