zoukankan      html  css  js  c++  java
  • F

    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;
        }
    }
    
    
  • 相关阅读:
    求最大的矩形(悬线法)
    限制不互素对的排列(构造)
    括号(构造)
    G. 4.奶牛(二进制枚举)
    新飞行棋(上楼梯)
    小天狼星的访问
    欧拉筛线性筛法,约数和和约数个数
    Find The Multiple
    How Many O's? UVA
    GCD LCM UVA
  • 原文地址:https://www.cnblogs.com/dchnzlh/p/10427284.html
Copyright © 2011-2022 走看看