luogu P1018 乘积最大

设有一个长度为$N$的数字串,要求选手使用$K$个乘号将它分成$K+1$个部分,找出一种分法,使得这$K+1$个部分的乘积能够为最大

$6 \le N \le 40,1 \le K \le 6$

看到有人在写这题……于是就$rush$了一波……

我居然还会写高精度

$f_{i,j}$表示处理完$[1,i]$后,用了$j$个乘号的最大值

显然$f_{i,j}=\max(f_{t,j-1} \times num_{t+1,i})$

于是做完了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 
 5 const int N = 100;
 6 
 7 struct Num {
 8     int a[N], len;
 9     Num() { len = 0, memset(a, 0, sizeof a); }
10     void output() {
11         for(int i = len - 1 ; ~ i ; -- i) printf("%d", a[i]);
12         puts("");
13     }
14 };
15 
16 Num operator * (Num a, Num b) {
17     Num c;
18     int len = a.len + b.len;
19     for(int i = 0 ; i < a.len ; ++ i)
20         for(int j = 0 ; j < b.len ; ++ j)
21             c.a[i + j] += a.a[i] * b.a[j];
22     for(int i = 0 ; i < len ; ++ i)
23         c.a[i + 1] += c.a[i] / 10, c.a[i] %= 10;
24     while(c.a[len - 1] == 0 && len - 1 >= 1) -- len;
25     c.len = len;
26     return c;
27 }
28 
29 Num f[60][10];
30 
31 char s[60];
32 
33 Num init(int n) {
34     Num c;
35     int len = n;
36     for(int i = 1 ; i <= n ; ++ i) {
37         c.a[n - i] = s[i] - '0';
38     }
39     while(c.a[len - 1] == 0 && len - 1 >= 1) -- len;
40     c.len = len;
41     return c;
42 }
43 
44 Num get(int l, int r) {
45     Num c;
46     int len = r - l + 1;
47     for(int i = l ; i <= r ; ++ i) {
48         c.a[r - i] = s[i] - '0';
49     }
50     while(c.a[len - 1] == 0 && len - 1 >= 1) -- len;
51     c.len = len;
52     return c;
53 }
54 
55 bool operator < (Num a, Num b) {
56     if(a.len != b.len) return a.len < b.len;
57     for(int i = a.len - 1 ; ~ i ; -- i)
58         if(a.a[i] != b.a[i])
59             return a.a[i] < b.a[i];
60     return 0;
61 }
62 
63 void read(Num &x) {
64     memset(x.a, 0, sizeof x.a);
65     scanf("%s", s + 1);
66     int n = strlen(s + 1);
67     for(int i = 1 ; i <= n ; ++ i)
68         x.a[n - i] = s[i] - '0';
69     while(x.a[n - 1] == 0 && n - 1 >= 1) -- n;
70     x.len = n;
71 }
72 
73 int main() {
74     
75 //    Num a, b;
76 //    read(a), read(b);
77 //    a.output(), b.output();
78 //    (a * b).output();
79 //    exit(0);
80     
81     int n, k;
82     scanf("%d%d%s", &n, &k, s + 1);
83     for(int i = 1 ; i <= n ; ++ i) {
84         f[i][0] = init(i);
85         for(int j = 1 ; j <= k ; ++ j) {
86             for(int t = 1 ; t <= i - 1 ; ++ t) {
87                 f[i][j] = max(f[i][j], f[t][j - 1] * get(t + 1, i));
88             }
89         }
90     }
91     f[n][k].output();
92 }
luogu P1018 乘积最大

转载于:https://www.cnblogs.com/KingSann/articles/9580999.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值