P1018 乘積最大(高精度 + dp)

題目鏈接:https://www.luogu.com.cn/problem/P1018

 

思路:

因爲20×20會超longlong,所以開個高精度,然後記錄dp[i][j]表示將1~j的數字分爲k段的最大值是多少,從前往後更新就好了。

最終輸出分爲k+1段後的結果即可。

(記第一個作對的綠題)

 

代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node
{
    int len = 0,nu[120] = {0};
}dp[10][55];
char ss[120];
Node f(int l,int r)
{
    Node tp;
    tp.len = r - l + 1;
    for(int i=r,j=1;j<=tp.len;i--,j++)
    {
        tp.nu[j] = (ss[i] - '0');
    }
    return tp;
}
void Pt(Node tp)
{
    for(int i=tp.len;i>=1;i--) printf("%d",tp.nu[i]);
    printf("\n");
}
Node Max(Node a,Node b)
{
    if(a.len > b.len) return a;
    else if(a.len < b.len) return b;
    for(int i=a.len;i>=1;i--)
        if(a.nu[i] > b.nu[i]) return a;
        else if(a.nu[i] < b.nu[i]) return b;
    return a;
}
Node Mul(Node a,Node b)
{
    Node c;
    for(int i=1;i<=a.len;i++)
    {
        for(int j=1;j<=b.len;j++)
            c.nu[i+j-1] += a.nu[i]*b.nu[j];
    }
    c.len = a.len + b.len-1;
    for(int i=1;i<=c.len;i++)
    {
        if(c.nu[i] >= 10)
        {
            if(i+1>c.len){
                c.len++;
            }
            c.nu[i+1] += c.nu[i]/10;
            c.nu[i] %= 10;
        }
    }
    while(c.len>=1 && c.nu[c.len] == 0) c.len--;
    if(c.len == 0)
    {
        c.nu[1] = 0;
        c.len = 1;
    }
    return c;
}
int main(void)
{
    int n,k;

    scanf("%d%d",&n,&k);
    scanf("%s",ss+1);
    //Pt(Mul(f(1,2),f(3,4)));
    for(int i=1;i<=k+1;i++)
    {
        for(int j=i;j<=n;j++)
        {
            if(i == 1) dp[i][j] = f(i,j);
            else{
                for(int t=i-1;t<j;t++) //注意,這裏t從i-1開始,因爲上次分爲了i-1段
                    dp[i][j] = Max(dp[i][j],Mul(dp[i-1][t],f(t+1,j)));
            }
        }
    }
    Pt(dp[k+1][n]);
    return 0;
}

 

發佈了448 篇原創文章 · 獲贊 17 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章