前言
真是一道 DFS 的好题啊,下次别出了。
题目
这个题我使用了记忆化搜索,记录当前搜到的点和分成的段数的乘积最大值,如果我们搜到这个点后发现这个点的记忆化数组比我们当前的乘积大就没必要再搜下去了,如果比我们的乘积小就更新记忆化数组为我们当前的乘积。
然后处理高精度,这里我推荐将高精度写成结构体,重载高精运算符,这样写着要自然一些。
建议压位,如果不压位可能会超时。
什么是压位?就是将整个数当做一个 1 0 k 10^k 10k 进制数, k k k 最好为 4 4 4,再使用特殊的输出方式,这样可以大大减少运算的次数。
AC Code:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int n, k;
string s;
const int base = 10000;
struct hi_pres{
int len, num[100];
hi_pres(){
len = 0;
memset(num, 0, sizeof(num));
}
};
const hi_pres base1;
int getlen(hi_pres a) {
for (int i = 90; i >= 0; i --) {
if (a.num[i]) return i;
}
return 0;
}
hi_pres operator + (const hi_pres a, const hi_pres b) {
int la = getlen(a), lb = getlen(b);
hi_pres c;
for (int i = 1; i <= max(la, lb); i ++) {
c.num[i] += a.num[i] + b.num[i];
c.num[i + 1] += c.num[i] / base;
c.num[i] %= base;
}
return c;
}
hi_pres operator * (const hi_pres a, const hi_pres b) {
int la = getlen(a), lb = getlen(b);
hi_pres c;
for (int i = 1; i <= la; i ++) {
for (int j = 1; j <= lb; j ++) {
c.num[i + j - 1] += a.num[i] * b.num[j];
c.num[i + j] += c.num[i + j - 1] / base;
c.num[i + j - 1] %= base;
}
}
return c;
}
hi_pres max(const hi_pres a, const hi_pres b) {
int la = getlen(a), lb = getlen(b);
if (la > lb) return a;
if (la < lb) return b;
for (int i = la; i >= 1; i --) {
if (a.num[i] > b.num[i]) return a;
if (a.num[i] < b.num[i]) return b;
}
return a;
}
hi_pres to_hi_pres(long long a) {
hi_pres c;
int i = 1;
while (a > 0) {
c.num[i] = a % base;
a -= a % base;
a /= base;
i ++;
}
return c;
}
hi_pres getnum(int l, int r) {
hi_pres ret;
for (int i = l; i <= r; i ++) {
ret = ret * to_hi_pres(10ll);
ret = ret + to_hi_pres(s[i] - '0');
}
return ret;
}
void print(hi_pres a) {
int la = getlen(a);
cout << a.num[la];
for (int i = la - 1; i >= 1; i --) {
int x = a.num[i];
if (x == 0) cout << "0000";
else if (x < 10) cout << "000" << x;
else if (x < 100) cout << "00" << x;
else if (x < 1000) cout << "0" << x;
else cout << x;
}
}
bool operator < (hi_pres a, hi_pres b) {
int la = getlen(a), lb = getlen(b);
if (la > lb) return 0;
for (int i = la; i >= 1; i --) {
if (a.num[i] > b.num[i]) return 0;
if (a.num[i] < b.num[i]) return 1;
}
return 0;
}
hi_pres ans;
hi_pres mem[100][10];
void dfs(int n1, int k1, hi_pres num) {
if (n1 == n) {
if (k1 == k + 1) {
ans = max(ans, num);
}
return ;
}
if (k1 > k + 1) return ;
if (num < mem[n1][k1]) return ;
else mem[n1][k1] = num;
for (int i = n1; i < n; i ++) {
dfs(i + 1, k1 + 1, num * getnum(n1, i));
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> k >> s;
dfs(0, 0, to_hi_pres(1));
print(ans);
return 0;
}