CF1735 A. Working Week
题目链接
https://codeforces.com/contest/1735/problem/A
题意简述
你的工作周由 \(n\) 天组成, \(n\) 天后又轮到第 \(1\) 天,并且他们其中包含 \(3\) 天休息日,其中第 \(n\) 天必须是休息日 , 现在需要你选择剩下两天休息日.
需要满足以下条件
- 这两天必须分开,不能连着. 提示:这也就意味着你不能选第一天作为休息日,因为它和第 \(n\) 天连着!
- 这几天休息日把工作日分割成一个个工作日的段,长度分别为 \(l_1 \ l_2\ l_3\)
请你调整休息日的安排,输出 \(min(\)\(|l_1-l_2|,|l_2-l_3|,|l_1-l_3|)\) 的最大值.
样例
点击查看样例
分析
题意即想让这三段连续工作日的时间的两两差值尽量的大,不妨让 \(l_1 \leq l_2 \leq l_3\) .
则有\(l_1\) 一定等于 \(1\) , 假设 \(l_1 > 1\),那么只要让 \(l_1\)减 \(1\) , 让 \(l_3\) 增大 \(1\) 结果就更优了(\(l_2-l_1\)不变, \(l_3-l_1\) 和 \(l_3-l_2\) 变大).
这三段两两的差值应该尽量接近,否则:如果有两段的差值变得更大,那么一定有两端的差值变得更小.
首先,一轮工作日去掉休息日有 \(n-3\) 天,\(1+l_2+l_3 = n-3\),其次,让两段工作日的时长尽量接近.\(l_3-l_2=l_2-1\)
那么只需解如下方程组
\(\left\{\begin{matrix}l_3-l_2=l_2-1\\ 1+l_2+l_3 = n-3 \end{matrix}\right.\)
联立方程组解得
\(l_2 = {n-3\over 3}\)
又由①可知 \(l_3\ = 2\ l_2-1\) 故有\(l_3-l_2 = l_2-1\)
并且因为 \(l_1=1\),所以\(l_2-l_1 =l_2-1\)
那么如果 $ 3\ |\ n-3\ $,结果一定是 \({n-3\over 3} - 1\)
如果不整除,, \(l_2\)若上取整(多1),根据\(1+l_2+l_3 = n-3\) ,那 \(l_3\)就得下取整(小1),最终\(|l_3-l_2|\)小了\(2\),显然\(l_3-l_2\)是最小值
\(l_2\)若下取整,那么\(l_2\)小了\(1\),最小值应该是\(l_2-1\),比上面的更大.所以下取整更优.那最终答案仍是\({n-3\over 3} - 1\)
代码
点击查看代码(比赛时写的麻烦的代码)
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
int main()
{
//freopen("uva.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
if((n-4)%3==0)
{
printf("%d\n",(n-4)/3-1);
}
else
{
printf("%d\n",(n-4)*2/3-(n-2)/3);
}
}
return 0;
}
- 正解代码
点击查看代码(正解代码)
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
printf("%d\n",(n-3)/3-1);
}
return 0;
}