二分算法

二分一定要是单调队列,单调才具有二段性

特征 最小值最大化 最大值最小化

15 届蓝桥杯 14 天省赛冲刺营 1 期 - M次方根 - 蓝桥云课 (lanqiao.cn)

#include <bits/stdc++.h> 
using namespace std;

double n,l,r,mid;
double eps=1e-8;

bool check(double mid,int m){//m次根下
    double c=1;
    while(m){
        c=c*mid;//s次根 
        m--;//c是mid的3次方 
    }
//要与别的条件扯上关系 在这里就是与n本身扯上关系
    if(c>=n)//如果mid的3次方大于等于n 
        return true;//还可以再小 
    else//如果mid的3次方下雨n 
        return false;//需要更大 
}

int main(){
    int m;
    cin>>n>>m;
//设置二分边界
    l=0,r=n;
//实数二分
    while (l + eps < r)
    {//mid是a可以的值 
        double mid = (l + r) / 2;
        if (check(mid,m))r = mid;
        else l = mid;
    }
    //一般使用print
    //printf("%x.yf",n)
    //其中X是固定整数长度,小数点前的整数位数不够,会在前面补0
    //y是保留小数位数,不够补零
    printf("%.7f",l);
    return 0;
}

15 届蓝桥杯 14 天省赛冲刺营 1 期 - 分巧克力 - 蓝桥云课 (lanqiao.cn)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int h[N],w[N];
int n,k;
bool check(int mid){//最大边长是mid
  int cnt=0;
  for(int i=1;i<=n;i++){
    int len=h[i]/mid;
    int wid=w[i]/mid;
    cnt+=len*wid;
  }
  return cnt>=k;
}
void solve(){
  cin>>n>>k;
  for(int i=1;i<=n;i++)cin>>h[i]>>w[i];
  int l=0,r=1e5+7;
  while(l<r){
    int mid=(l+r+1)>>1;
      if(check(mid))l=mid;//还可以更多
      else r=mid-1;
  }
  cout<<l;
  return ;
}
int main(){
  int t=1;
  while(t--)solve();
  return 0;
}

1.跳石头 - 蓝桥云课 (lanqiao.cn)

#include <bits/stdc++.h>
using namespace std;
const int N=5e4+7;
int l,n,m;
int stones[N];
bool check(int mid){//最短跳跃距离
  int pos=0;//记录目前在哪个石头上目前在起点石头上
  int cnt=0;//搬走多少个石头
  for (int i = 1; i <= m+1; i++)
        if (stones[i] - stones[pos] < mid)
            cnt++;//小于最小跳跃距离就搬走石头i然后去看下一个石头
        else pos = i;//否则跳上
    if (cnt <= n) return true;//最短跳远距离mid还可以更大
    return false;
}
void solve(){
  cin>>l>>m>>n;//起点到终点的距离 岩石数 至多移走
  for(int i=1;i<=m;i++){
    cin>>stones[i];//表示第i个石头到起点stones[0]的距离
  }
  stones[m+1]=l;//终点石头
  int l=1,r=1e9+7;//最短的跳远距离
  while(l<r){
    int mid=(l+r+1)>>1;
    if(check(mid))l=mid;
    else r=mid-1;
  }
  cout<<l;
  return ;
}
int main(){
  int t=1;
  while(t--)solve();
  return 0;
}

1.解立方根 - 蓝桥云课 (lanqiao.cn)

#include <bits/stdc++.h>
using namespace std;
double n;
double eps=0.0001;
bool check(double mid,int m){//m次方
  double res=1;
  while(m--){
    res*=mid;//得到这个数的m次方
  }
  if(res>=n)return true;
  else return false;
}
void solve(){
  cin>>n;
  double l=0,r=n;
  while(l+eps<r){
    double mid=(l+r)/2;//不能位运算了
    if(check(mid,3))r=mid;//还能更小
    else l=mid;
  }
  printf("%.3lf\n",l);
  return ;
}
int main(){
  int t=1;cin>>t;
  while(t--)solve();
  return 0;
}

730. 机器人跳跃问题 - AcWing题库

//二分求解
#include<bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int n;
int h[N];
int maxh=-0x3f3f;
bool check(int x){
    for(int i = 1; i <= n; i++)
    {
        x = 2 * x - h[i];
        if(x < 0) return false;
        if(x > maxh) return true;//加速
        //因为公式是 2E-h[i]如果已经大于最高高度了 那么后面一定越来越大
    }
    return true;
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++) {
      cin >> h[i];
      maxh=max(maxh,h[i]);
}
    int l = 1, r = 1e5;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(check(mid)) r = mid;
        else l = mid + 1; 
    }

    cout << l << '\n';

    return 0;
}

 

//递推解方程
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;

int n;
int h[N];
double p[N];//存放2的次幂

int main(){
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> h[i];

    p[0] = 1;//2^0=1

    double res = 0;
    for(int i = 1; i <= n; i++)
    {
        p[i] = p[i - 1] * 2;
        res += (1.0 / p[i]) * h[i];
    }

    cout << ceil(res) << '\n';

    return 0;
}

 1221. 四平方和 - AcWing题库

//写法1:暴力
#include <bits/stdc++.h>
using namespace std;
const int N = 5e6+7;
int n;
signed main () {
    int n;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 temp=n-(a*a+b*b+c*c);
    			int d=sqrt(temp);//注意这里的处理 保证是一个平方数
    			if(d*d==temp&&d>=c){
    				printf("%d %d %d %d",a,b,c,d);
    				return 0;
				}
			}
		}
	}
	return 0;
}

//写法2:排序后二分
#include <bits/stdc++.h>
using namespace std;
const int N = 5e6+7;
int n;
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 m=1;
signed main () {
    int n;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=a;a*a+b*b<=n;b++){
			int t=n-a*a-b*b;
			int l=1,r=m;
			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;
}

//解法3:unordered_map 自带的哈希表 但是会超时 可以用手写哈希表优化
#include <bits/stdc++.h>
#define int long long
#define x first
#define y second
using namespace std;

const int N = 5e6+7;
int n;
unordered_map<int, pair<int,int> > has;

signed 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 (has.count(t) == 0) has[t] = {c, d};
        }
    }

    for (int a = 0; a * a <= n; a++) {
        for (int b = a; a * a + b * b <= n; b++) {
            int t = n - a * a - b * b;
            if (has.count(t)) {
                printf("%d %d %d %d\n", a, b, has[t].x, has[t].y);
                return 0;
            }
        }
    }

    return 0;
}

//写法3:模拟哈希表
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N = 5e6 + 10;
int n;
int has[N * 2];//小技巧,避免pair,r[c^2+d^2]=c;可以推导出d
模拟哈希表

int main(){
    cin >> n;

    memset(has, -1, sizeof has);

    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(has[t] == -1)//如果存过才存 为了保证字典序最小
            {
                has[t] = c;//只存下来c就可以了
            }
        }
    }

    for(int a = 0; a * a <= n; a ++)
    {
        for(int b = a; a * a + b * b <= n; b++)
        {
            int t = n - a * a - b * b;
            int c = has[t];
            if(has[t] == -1) continue;
            int d = sqrt(t - c * c);//这里已经能保证是一个平方数了
            printf("%d %d %d %d\n", a, b, c, d);
            return 0;
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值