Title Link https://www.luogu.com.cn/problem/P1018

This year is the "2000 - world year of mathematics" determined by the International Mathematical Union, and coincides with the 90th anniversary of the birth of Mr. Hua Luogeng, a famous mathematician in China. In Jintan, Jiangsu, Mr. Hua Luogeng's hometown, a new mathematical intelligence contest was organized, and one of your good friends XZ was lucky to participate. During the activity, the host gave all the participants a question:

There is a number string with a length of N. players are required to use K multiplication signs to divide it into K+1 parts, and find a division method to maximize the product of K+1 parts.

At the same time, in order to help the contestants correctly understand the meaning of the question, the host also gave the following example:

There is a number string: 312. When n = 3 and K = 1, there are the following two methods:

- 3×12=36
- 31×2=62

At this time, the result that meets the requirements of the topic is: 31 × 2=62

Now, please help your good friend XZ design a program to get the right answer. (6≤N≤40,1≤K≤6)

From the topic and data range, it is easy to think of applying DP method to this topic,

dp[i][k [represents the number of the first I, which is the maximum value when divided into k segments

So we need to enumerate where the last multiplication sign is placed

When transferring, directly calculate the maximum value when the number before the last multiplier is divided into k-1 segment, and then multiply it by the number after the last multiplier.

Note: the number in this question is too large and should be calculated with high precision. Because we need to use many parts in the middle of the original number, we can preprocess the size of all subsequences of the original number first, and the final multiplication is high precision

AC code (note in detail)

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int N = 50; char s[N]; int a[N][N][N], f[N][10][50000]; void modify(int x, int s, int m) {//f[m - 1][s - 1][0] because it is disposed from m, the front is m-1, and the front is s-1 before transfer int ans[50000];//!!! Originally, P > = J corresponds to M-1 > = S-1 here memset(ans, 0, sizeof(ans)); for(int i = 1; i <= a[m][x][0]; i++) for(int j = 1; j <= f[m - 1][s - 1][0]; j++)//!!!! m-1 note that the array may be out of bounds to - 1!!! ans[i + j - 1] += a[m][x][i] * f[m - 1][s - 1][j];//Similar to multiplication column vertical calculation for(int i = 1; i <= a[m][x][0] + f[m - 1][s - 1][0]; i++) { if(ans[i]) ans[0] = i; ans[i + 1] += ans[i] / 10;//Carry processing ans[i] %= 10; } if(ans[0] < f[x][s][0]) return; for(int i = ans[0]; i >= 1; i--) { if(ans[i] > f[x][s][i]) break; if(ans[i] < f[x][s][i]) return; }//Judge whether to update for(int i = 0; i <= ans[0]; i++) f[x][s][i] = ans[i]; return; } int main() { int n, k; scanf("%d%d", &n, &k); scanf("%s", s + 1); for(int i = 1; i <= n; i++) for(int j = i; j <= n; j++) { a[i][j][0] = j - i + 1; for(int p = j - i + 1; p >= 1; p--) a[i][j][j - i + 2 - p] = s[i + p - 1] - '0'; }//Method of converting string to high precision for(int i = 1; i <= n; i++) for(int j = 1; j <= i && j <= k + 1; j++)//The first i position can be k+1 segment or i segment at most { if(j == 1)//j=1 is the boundary, that is, there is only one section without multiplication sign { f[i][j][0] = i; for(int p = 1; p <= i; p++) f[i][j][p] = a[1][i][p]; } for(int p = i; p >= j; p--)//Because f[i][j] is the first I digit and is divided into several segments, the minimum I must also be j modify(i, j, p);//!! The function variable represents that the first i bit is divided into j segments and transferred from p } for(int i = f[n][k + 1][0]; i >= 1; i--) printf("%d", f[n][k + 1][i]); return 0; }