第一问和第二问分开处理,第一问二分回答,第二问Dp,要用辅助数组,以空间换时间,复杂度可以做到O(NM)
const int N = 50005, M = 1005, MOD = 10007;
int Dat[N], n, m, s[N];
inline void Input() {
scanf("%d%d", &n, &m);
For(i, 1, n) scanf("%d", &Dat[i]), s[i] = s[i - 1] + Dat[i];
}
inline bool Check(int len) {
int cnt = 0, t = 0;
For(i, 1, n) {
t += Dat[i];
if (t > len) cnt++, t = Dat[i];
if (t > len) return 0;
if (cnt == m + 1) return 0;
}
return (++cnt) <= m + 1;
}
inline int work() {
int Min = INF;
For(i, 1, n) Min = min(Min, Dat[i]);
int l = Min, r = s[n];
while(l < r) {
int mid = (l + r) >> 1;
Check(mid) ? r = mid : l = mid + 1;
}
return l;
}
int Dp[2][N];
int pos[N], q[N], head, tail, S[N];
inline void Solve() {
int ans = work();
printf("%d ", ans);
head = tail = q[1] = pos[1] = 1;
For(i, 2, n) {
while(head <= tail && s[q[head]] < s[i] - ans) head++;
pos[i] = q[head], q[++tail] = i;
}
int *now = Dp[0], *prev = Dp[1], T;
T = 0;
For(i, 1, n) {
if((T += Dat[i]) > ans) break;
prev[i] = 1;
}
For(i, 1, n) S[i] = (S[i - 1] + prev[i]) % MOD;
int cnt = prev[n] % MOD;
For(j, 1, m) {
For(i, 1, n) now[i] = (S[i - 1] - S[pos[i] - 1] + MOD) % MOD;
For(i, 1, n) S[i] = (S[i - 1] + now[i]) % MOD;
cnt = (cnt + now[n]) % MOD;
swap(now, prev);
}
printf("%d\n", cnt);
}
int main() {
Input();
Solve();
return 0;
}