P1018 乘积最大

水题刷成模板题。。。


这道题本来方程不难想的。

\(dp[i][j]\)为前\(i\)位中添加了\(j\)个乘号的乘积最大值。

状态转移方程:\(dp[i][j] = max(dp[i][j], dp[k][j - 1] \times sp[k + 1][i])\)

初始状态为\(dp[i][0] = sp[0][i]\),而不是\(dp[i][i]\)!时刻记住你定义的方程!

那么按理来说跑一跑就能过了。

但是致命的来了:\(N \leq 40\)

你见过什么能够存40位的数据类型吗?long long也才17位。

所以:高精度乘法!

实现方法也很简单:

同样像历来的高精一样的做法,逆序储存数字。

当第一个数的第\(i\)位与与第二个数的第\(j\)位相乘,答案会在第\(i+j\)位上!

然后注意进位,最后处理一下长度即可。长度最好先设为两个len之和,算完之后再来删除前导0。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>


const int maxbit = 205;
struct BigInt
{
    int a[maxbit], len;
    void print()
    {
        for(int i = len - 1; i >= 0; i--)
        {
            printf("%d", a[i]);
        }
        //printf("\n");
    }
    void init(char *ch)
    {
        memset(a, 0, sizeof(a));
        len = strlen(ch);
        for(int i = len - 1; i >= 0; i--) a[len - i - 1] = ch[i] - '0';
    }
    BigInt operator * (const BigInt rhs) const
    {
        BigInt ans;
        memset(ans.a, 0, sizeof(ans.a));
        ans.len = len + rhs.len;
        for(int i = 0; i < len; i++)
        {
            for(int j = 0; j < rhs.len; j++)
            {
                ans.a[i + j] += a[i] * rhs.a[j];
                if(ans.a[i + j] >= 10)
                {
                    ans.a[i + j + 1] += ans.a[i + j] / 10;
                    ans.a[i + j] %= 10;
                }
            }
        }
        while(ans.len - 1 > 0 && ans.a[ans.len - 1] == 0) ans.len--;
        return ans;
    }
    bool operator < (const BigInt rhs) const
    {
        if(len > rhs.len) return false;
        else if(len < rhs.len) return true;
        for(int i = len - 1; i >= 0; i--)
        {
            if(a[i] > rhs.a[i]) return false;
            else if(a[i] < rhs.a[i]) return true;
        }
        return false;
    }
};

BigInt dp[50][10];
BigInt sp[50][50];
BigInt Std;
int n, m;

BigInt split(int s, int t)
{
    BigInt ans;
    ans.len = t - s + 1;
    for(int i = s; i <= t; i++)
    {
        ans.a[i - s] = Std.a[i];
    }
    return ans;
}

char temp[maxbit];
int main()
{
    scanf("%d%d", &n, &m);
    scanf("%s", temp);
    Std.init(temp);
    for(int i = 0; i < n; i++)
    {
        for(int j = i; j < n; j++)
        {
            sp[i][j] = split(i, j);
            //sp[i][j].print(); printf("\n");
        }
    }
    for(int i = 0; i < n; i++) dp[i][0] = sp[0][i];
    for(int i = 0; i < n; i++)
    
    {
        for(int j = 1; j <= m; j++)
        {
            for(int k = 0; k < i; k++)
            {
                BigInt temp1 = dp[i][j];
                //temp1.print(); printf("\n");
                BigInt temp2 = dp[k][j - 1] * sp[k + 1][i];
                //temp2.print(); printf("\n");
                dp[i][j] = std::max(dp[i][j], dp[k][j - 1] * sp[k + 1][i]);
            }
        }
    }
    dp[n - 1][m].print();
    return 0;
}
posted @ 2018-08-14 14:01  Garen-Wang  阅读(191)  评论(0编辑  收藏  举报