P11181 [ROIR 2018 Day2] 书页 题解

题目传送门

前言

经历了 3 3 3 次提交终于通过了,顺便抢到了次优解。然后觉得自己运气较好,准备写一篇题解庆祝一下,结果写到一半,电脑没电了。不死心的我就写了这篇题解。

解题思路

这是一道贪心,对我而言这个贪心不是特别明显,最近 DP 做多了得了后遗症,一上来就想 DP,然后发现我太菜了,根本不会。

根据题意,我得出了以下简单结论:

  1. k k k 页一定是插图。
  2. 如果需要在第 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+1qi)s

下面就是简单结论的应用了。

  • 如果 a ≤ s + p a \leq s + p as+p,我们在第一个文本前面插入一张插图,使得 a a a 增大 p p p
  • 如果 s + p < a < s s + p < a < s s+p<a<s,我们只需要在第 s − a s - a sa 个文本前插入插图即可。
  • 重复执行上述操作,直到 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+qksa+[(sa)mod(qk)=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;
}

猜你喜欢

转载自blog.csdn.net/2301_76224755/article/details/143119472