codeforces1303B National Project 二分或直接计算
网址:https://codeforces.com/contest/1303/problem/B
题意:
修一条长度为$n$的路,要求至少一半是$good$的。在一个周期中,第$[1,g]$天可以修$good$的路,第$[g+1,g+b]$天可以修$bad$的路,依次交替。问按要求修完整条路需要的最短时间。
题解:
解法1:
直接计算。先考虑$g<b$,对于$good$状态的路,我们需要一个周期中所有$good$的天数修出$good$的路,然后修$1 \leq t \leq g$天的$bad$的路。然后对于剩下不满一个周期的路。如果刚好已经修完,因为$g<b$,所以可知$bad$的路一定在$good$的路修完了之前已经修完了$\lfloor n/2 \rfloor$,所以最后一个周期的$bad$天数是不需要的,直接减去,如果剩下了,就加上$\lceil x/2 \rceil$ $mod$ $good$的天数。所以$ans=\lceil n/2 \rceil/g*(g+b)+(\lceil n/2 \rceil%g==0?-b:\lceil n/2 \rceil%g)$。对于$g \geq b$的情况显然直接输出$n$,此时$n$一定比$ans$大,所以输出$max(ans,n)$,就不用特判了。
AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; void solve() { ll n, g, b; scanf("%lld%lld%lld", &n, &g, &b); ll tmp = (n + 1) / 2; ll tot = tmp / g * (g + b); if (tmp % g == 0) tot -= b; else tot += tmp % g; printf("%lld\n", max(tot, n)); } int main() { int t; scanf("%d", &t); while (t--) solve(); return 0; }
$*$向上取整的整数除法写法是$(x+n-1)/n$。
解法2:
二分就是判断给出的$t$天能不能完成这个工程,显然如果$t$天中$good$的天数都不够$\lceil n/2 \rceil$的肯定不行,否则就可以,二分的下界是$n$,上界直接$INF$,不差那点时间。
AC代码:
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; typedef long long ll; bool check(ll n, ll g, ll b, ll t) { return (n + 1) / 2 <= t / (g + b) * g + min(g, t % (g + b)); } void solve() { ll n, g, b; scanf("%lld%lld%lld", &n, &g, &b); ll l = n, r = 1e18; while (l < r) { ll m = (l + r) >> 1; if (check(n, g, b, m)) r = m; else l = m + 1; } printf("%lld\n", l); } int main() { int t; scanf("%d", &t); while (t--) solve(); return 0; }