題目鏈接: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;
}