在进行第一次和学长进行组队赛的时候,碰见一个二分的题(但当时我们并没有看出来,学长他们都是二分过了,我们还在卡..)
题目链接:https://codeforces.com/gym/103688/problem/A
题目大意:
给你书架的高度,给你两种书(一高一低),并且分别给你他们的本数,要求用最小的宽度,将他们全放进去。
一开始我们通过画图,大概思路是先放短的书那一部分,看看在上边能够放置多少,然后将剩下的书,排一排,一本一本取,看看能再减少多少宽度。
由于我们做题不多,对二分的了解少。我们一开始把这个当成的一个思维题,通过解方程,处理了各种精度问题,最终花费大量时间,解决了问题;
时间复杂度O(1),速度很快,但是想的很慢。(
Code:
#include<bits/stdc++.h>
#define ll long long
#define pll pair < ll , ll >
#define buff ios::sync_with_stdio(false)
using namespace std;
const int N = 1e6 + 10;
int main()
{
buff;
int t;
cin>>t;
while (t--) {
ll a, b, n, m, h;
cin>>a>>b>>n>>m>>h;
if ((n / b) * (b - a) >= m - 1) {
cout<<n + 1<<"\n";
continue;
}
m = m - (n / b) * (b - a);
if (b == h) {
cout<<n + m<<"\n";
continue;
}
ll cnt = (n+m)/h;
ll cnt1=(m-1)/(h-b);
cnt=min(cnt,cnt1);
if(cnt*(h-b)>m-1&&cnt>0)cnt--;
ll ans=n+m-(cnt*(h-b));
m-=cnt*(h-b);
if(ans-cnt*b>b&&m>1)
{
ll j1=(ans-cnt*b)-b;
ll j2=m-1;
j1=min(j1,j2);
ans-=j1;
}
cout<<ans<<"\n";
// if (((n + 1) / b) * (h - b) >= m - 1) {
// cout<<n + 1<<"\n";
// continue;
// }
// m = m -(((n + 1) / b) * (h - b));
// ll len = b * (m / h);
// ll cnt = (m / h) * h;
// cout<<n + 1 + len + (m - cnt)<<"\n";
// m = m - (n / b) * (h - b);
// if (b == h) {
// cout<<n + m<<"\n";
// continue;
// }
//
// ll x = (b - n % b);
// if (x >= m) {
// cout<<n + m<<"\n";
// continue;
// }
// if (m - x <= h - b) {
// cout<<n + x<<"\n";
// continue;
// }
// m = m - x - (h - b);
// ll len = b * (m / h);
// ll cnt = (m / h) * h;
// cout<<n + x + len + (m - cnt)<<"\n";
// if (m >= b)
// {
// cout << n + x + min(m - b,h - b) * << "\n";
// continue;
// }
// if(m < b)
// {
// cout << n + x + m << "\n";
// }
}
return 0;
}
另一种写法是二分写法,直接通过对长度的二分,然后一次次缩短范围得到一个准确结果。
思路是一样的,只不过是用二分,让电脑进行判断长度是否合理,十分简便。
时间复杂度比上一个高,但是方便很多。
Code :
#include<bits/stdc++.h>
#define ll long long
#define pll pair < ll , ll >
#define buff ios::sync_with_stdio(false)
using namespace std;
const int N = 1e6 + 10;
const int mod = 998244353;
ll a,b,n,m,h;
bool check(ll x)
{
if((b - a) * (n / b) + x + (n + x) / b * (h - b) >= m)
{
return 1;
}
return 0;
}
int main()
{
buff;
ll t;
cin >> t;
while(t --)
{
cin >> a >> b >> n >> m >> h;
ll l = 1,r = m;
while(l < r)
{
ll mid = (l + r) >> 1;
if(check(mid))
{
r = mid;
}
else
{
l = mid + 1;
}
}
cout << n + l << endl;
}
}
虽然我们写的很慢,但是我们还是对那个方法比较骄傲(bushi