题目传送门
前言
经历了 3 3 3 次提交终于通过了,顺便抢到了次优解。然后觉得自己运气较好,准备写一篇题解庆祝一下,结果写到一半,电脑没电了。不死心的我就写了这篇题解。
解题思路
这是一道贪心,对我而言这个贪心不是特别明显,最近 DP 做多了得了后遗症,一上来就想 DP,然后发现我太菜了,根本不会。
根据题意,我得出了以下简单结论:
- 前 k k k 页一定是插图。
- 如果需要在第 i i i 页前插一张插图,那么文本页码的总和就会在原来的基础上加上 p p p, p p p 为第 i i i 页后的文本的个数。
不要认为这些结论简单然后觉得没用,因为简单意味着牢固。
由于需要满足插图越少越好,所以我们的文本一定是越靠前越好,比如 s = 6 s = 6 s=6,那么 111 111 111 一定比 000001 000001 000001 更优( 1 1 1 是文本, 0 0 0 是插图)。
所以我们可以找到一个最大的 q q q 使得 a = ( ∑ i = k + 1 q i ) ≤ s a = (\sum\limits_{i = k + 1} ^ {q} i) \leq s a=(i=k+1∑qi)≤s。
下面就是简单结论的应用了。
- 如果 a ≤ s + p a \leq s + p a≤s+p,我们在第一个文本前面插入一张插图,使得 a a a 增大 p p p。
- 如果 s + p < a < s s + p < a < s s+p<a<s,我们只需要在第 s − a s - a s−a 个文本前插入插图即可。
- 重复执行上述操作,直到 a = s a = s a=s。
所以答案就是 k + s − a q − k + [ ( s − a ) m o d ( q − k ) ≠ 0 ] k + \frac{s - a}{q - k} + [(s - a) \bmod (q - k) \neq 0] k+q−ks−a+[(s−a)mod(q−k)=0]。
这里的中括号是艾佛森括号,括号中的条件成立则为 1 1 1,不成立为 0 0 0。
注意: for
循环会先执行 i++
再判断条件是否成立,所以我们需要在退出循环后执行 i--
。
CODE:
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
ios::sync_with_stdio(false);
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int k, s;
cin >> k >> s;
int sum = 0, ans = k, i;
for (i = k + 1; sum <= s; i++) {
sum += i;
}
i--; //你猜,见《注意》。
while (sum > s) {
sum -= i;
i--;
}
if (s - sum) {
ans += (s - sum) / (i - k); //减一加一互相抵消掉了。
if ((s - sum) % (i - k))
ans++;
}
cout << ans;
return 0;
}