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;
}

 

posted @ 2020-02-17 12:41  Aya_Uchida  阅读(197)  评论(0编辑  收藏  举报