二分
整数二分步骤:
1.找一个区间[L,R],使得答案一定在该区间中。
2.找一个判断条件,使得该判断条件具有二段性,并且答案一定在该二段性的分界点。
3.分析终点M在该判断条件下是否成立,如果成立,考虑答案在哪个区间,如果不成立,考虑答案在那个区间。
4.如果更新方式写的是R = Mid,则不用做任何处理;如果更新方式写的是L = Mid,则需要在计算Mid时加上1。
![在这里插入图片描述](https://img-blog.csdnimg.cn/d9e626c4309b4ee4be99e8c2e8ef703b.png)
1.数的范围789
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, m;
int q[N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
for (int i = 0; i < m; i ++ )
{
int x;
scanf("%d", &x);
// 二分x的左端点
int l = 0, r = n - 1; // 确定区间范围
while (l < r)
{
int mid = l + r >> 1;//除2
if (q[mid] >= x) r = mid;
else l = mid + 1;
}
if (q[r] == x)
{
cout << r << ' ';
// 二分x的右端点
r = n - 1; // 右端点一定在[左端点, n - 1] 之间
while (l < r)
{
int mid = l + r + 1 >> 1; // 因为写的是l = mid,所以需要补上1
if (q[mid] <= x) l = mid;
else r = mid - 1;
}
cout << r << endl;
}
else cout << "-1 -1" << endl;
}
return 0;
}
2.数的三次方跟790
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
double x;
cin >> x;
double l = -10000, r = 10000;
while (r - l > 1e-8)
{
double mid = (l + r) / 2;
if (mid * mid * mid >= x) r = mid;
else l = mid;
}
printf("%lf\n", l);
return 0;
}
3. 机器人跳跃问题730
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int num[N];
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++)cin>>num[i];
int res = 0;
for(int i = n - 1; i >= 0; i--){
if((num[i] + res) % 2 == 0)
res = (num[i] + res) / 2;
else
res = (num[i] + res) / 2 + 1;
}
cout<<res<<endl;
}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int h[N];
bool check(int e)
{
for (int i = 1; i <= n; i ++ )
{
e = e * 2 - h[i];
if (e >= 1e5) return true;
if (e < 0) return false;
}
return true;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
int l = 0, r = 1e5;
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
return 0;
}
4. 四平方和1221
#include <cstring> //暴力
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 2500010;
int n;
int main()
{
cin >> n;
for (int a = 0; a * a <= n; a ++ )
for (int b = a; a * a + b * b <= n; b ++ )
for (int c = b; a * a + b * b + c * c <= n; c ++ )
{
int t = n - a * a - b * b - c * c;
int d = sqrt(t);
if (d * d == t)
{
printf("%d %d %d %d\n", a, b, c, d);
return 0;
}
}
}
#include <cstring> //二分
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 2500010;
struct Sum
{
int s, c, d;
bool operator< (const Sum &t)const
{
if (s != t.s) return s < t.s;
if (c != t.c) return c < t.c;
return d < t.d;
}
}sum[N];
int n, m;
int main()
{
cin >> n;
for (int c = 0; c * c <= n; c ++ )
for (int d = c; c * c + d * d <= n; d ++ )
sum[m ++ ] = {
c * c + d * d, c, d};
sort(sum, sum + m);
for (int a = 0; a * a <= n; a ++ )
for (int b = 0; a * a + b * b <= n; b ++ )
{
int t = n - a * a - b * b;
int l = 0, r = m - 1;
while (l < r)
{
int mid = l + r >> 1;
if (sum[mid].s >= t) r = mid;
else l = mid + 1;
}
if (sum[l].s == t)
{
printf("%d %d %d %d\n", a, b, sum[l].c, sum[l].d);
return 0;
}
}
return 0;
}
#include <cstring> //哈希表
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 2500010;
int n, m;
unordered_map<int, PII> S;
int main()
{
cin >> n;
for (int c = 0; c * c <= n; c ++ )
for (int d = c; c * c + d * d <= n; d ++ )
{
int t = c * c + d * d;
if (S.count(t) == 0) S[t] = {
c, d};
}
for (int a = 0; a * a <= n; a ++ )
for (int b = 0; a * a + b * b <= n; b ++ )
{
int t = n - a * a - b * b;
if (S.count(t))
{
printf("%d %d %d %d\n", a, b, S[t].x, S[t].y);
return 0;
}
}
return 0;
}
5.分巧克力1227
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, k;
int h[N], w[N];//存储长、宽
bool check(int mid)
{
int res = 0;//记录分成长度为 a 的巧克力数量
for (int i = 0; i < n; i ++ )
{
res += (h[i] / mid) * (w[i] / mid);//每一大块可以分成的边长为 a 的巧克力数量
if (res >= k) return true;//大于要求数量,返回真
}
return false;
}
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i ++ ) scanf("%d%d", &h[i], &w[i]);
int l = 1, r = 1e5;
while (l < r)//二分小巧克力边长范围,找到符合要求的最大值
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
printf("%d\n", r);
return 0;
}