COJ 1026 乘积最大 DP+高精度

这题用DP或者DFS均能过。 在COJ上看了ahyangyi大神的代码,手写了个bigint的结构体,遂模仿之,果然很好使


典型的DP问题
设w(h,q)表示从h位开始的q位数字组合所成的十进制数,m(i,j)表示前i位数字串插入j个乘号所得的最大乘积,初始值为:
m(i,0) = w(0,q) ;


动规方程如下所示:
if (j==0) m(i,j) = w(0,i) ;
else if(j>0)
m(i,j) = max { m(d,j-1)*w(d+1,i-d) } ps: 其中 0<= d < i

下标均从0开始

DP版本

/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define INF 2000000000
#define MAXN 100005
#define eps 1e-10
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
struct BigInteger
{
    int len;
    int d[105];
    BigInteger(){len = 1; d[0] = 0;}
    BigInteger(string s)
    {
        len = s.length();
        reverse(s.begin(), s.end());
        for(int i = 0; i < len; i++)
            d[i] = s[i] - '0';
        while(len > 0 && d[len - 1] == 0) len--;
        if(!len) d[len++] = 0;
    }
    void operator *=(const BigInteger &a)
    {
        int tmp[105];
        for(int i = 0; i < len + a.len; i++) tmp[i] = 0;
        for(int i = 0; i < len; i++)
            for(int j = 0; j < a.len; j++)
                tmp[i + j] += d[i] * a.d[j];
        len = len + a.len - 1;
        for(int i = 0; i < len; i++)
        {
            tmp[i + 1] += tmp[i] / 10;
            tmp[i] %= 10;
        }
        if(tmp[len]) len++;
        for(int i = 0; i < len; i++) d[i] = tmp[i];
        while(len > 0 && d[len - 1] == 0) len--;
        if(!len) d[len++] = 0;
    }
    bool operator <(const BigInteger &a)const
    {
        if(len != a.len) return len < a.len;
        for(int i = len - 1; i >= 0; i--)
            if(d[i] != a.d[i]) return d[i] < a.d[i];
        return false;
    }
    void out()
    {
        for(int i = len - 1; i >= 0; i--)
        printf("%d", d[i]);
        printf("\n");
    }
}dp[55][11];
int n, m;
char s[105];
int main()
{
    scanf("%d%d%s", &n, &m, s);
    string tx = s;
    for(int i = 0; i < n; i++)
    {
        dp[i][0] = BigInteger(tx.substr(0, i + 1));
        for(int j = 1; j <= m; j++)
        {
            for(int k = 0; k < i; k++)
            {
                BigInteger q(tx.substr(k + 1, i - k));
                q *= dp[k][j - 1];
                if(dp[i][j] < q) dp[i][j] = q;
            }
        }
    }
    dp[n - 1][m].out();
    return 0;
}

DFS版本


/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define INF 2000000000
#define MAXN 100005
#define eps 1e-10
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
struct BigInteger
{
    int len;
    int d[105];
    BigInteger(){len = 1; memset(d, 0, sizeof(d)); d[0] = 1;}
    BigInteger(string s)
    {
        len = s.length();
        for(int i = 0; i < len; i++)
            d[i] = s[i] - '0';
        while(len > 0 && d[len - 1] == 0) len--;
        if(!len) d[len++] = 0;
    }
    void operator *=(const BigInteger &a)
    {
        int tmp[105];
        for(int i = 0; i < len + a.len; i++) tmp[i] = 0;
        for(int i = 0; i < len; i++)
            for(int j = 0; j < a.len; j++)
                tmp[i + j] += d[i] * a.d[j];
        len = len + a.len - 1;
        for(int i = 0; i < len; i++)
        {
            tmp[i + 1] += tmp[i] / 10;
            tmp[i] %= 10;
        }
        if(tmp[len]) len++;
        for(int i = 0; i < len; i++) d[i] = tmp[i];
        while(len > 0 && d[len - 1] == 0) len--;
        if(!len) d[len++] = 0;
    }
    bool operator <(const BigInteger &a)const
    {
        if(len != a.len) return len < a.len;
        for(int i = len - 1; i >= 0; i--)
            if(d[i] != a.d[i]) return d[i] < a.d[i];
        return false;
    }
    void out()
    {
        for(int i = len - 1; i >= 0; i--)
        printf("%d", d[i]);
        printf("\n");
    }
}ans;
int n, k;
char s[105];
void dfs(BigInteger t, int m, int x)
{
    if(m == 0)
    {
        if(ans < t) ans = t;
        return;
    }
    for(int i = x ; i < n - m + 1; i++)
    {
        BigInteger q = t;
        string fk = s;
        fk = fk.substr(x, i - x + 1);
        reverse(fk.begin(), fk.end());
        q *= BigInteger(fk);
        dfs(q, m - 1, i + 1);
    }
}
int main()
{
    scanf("%d%d%s", &n, &k, s);
    ans.d[0] = 0;
    BigInteger t;
    dfs(t, k + 1, 0);
    ans.out();
    return 0;
}


在计算机科学中,尤其是在线竞赛(OJ,Online Judge)中,处理高精度加法是一个常见的任务,因为通常涉及的大整数超出了标准数据类型(如int或long long)的范围。在C语言中,要实现高精度加法,一种常用的方法是使用数组或者动态内存分配来存储大整数,并逐位进行加法运算。 以下是一个简单的高精度加法算法的步骤: 1. 定义两个大整数数组,每个元素存储一位数字。 2. 初始化两个指针,分别指向这两个数组的末尾。 3. 当两个指针所指向的位数不相同时,将较小数组的剩余位补零。 4. 对应位置的数字进行加法(0-9,10可能需要进位),并更新结果数组。 5. 如果在某个步骤发生了进位,需要在前一个位置增加1。 6. 指针向前移动一位,直到其中一个指针达到数组末尾。 7. 如果还有剩余的进位,将它加到结果数组的最前面。 这是一个简化版的描述,实际的代码实现会涉及到更多的边界检查和错误处理。下面是一个简化的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #define MAX_DIGITS 10000 // 可以根据需要调整 char* addStrings(char* str1, char* str2) { int len1 = strlen(str1); int len2 = strlen(str2); int max_len = len1 > len2 ? len1 : len2; int carry = 0; char* result = (char*)malloc((max_len + 1) * sizeof(char)); result[max_len] = '\0'; for (int i = max_len - 1; i >= 0; --i) { int sum = carry + (str1[i] - '0') + (str2[i] - '0'); result[i] = sum % 10 + '0'; carry = sum / 10; } if (carry) { result = carry + '0'; } return result; } int main() { char* str1 = "123456789"; char* str2 = "987654321"; char* result = addStrings(str1, str2); printf("Result: %s\n", result); free(result); // 一定要记得释放动态内存 return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值