二分模板:
int l=???,r=???,mid;//看具体情况
while(l<=r){
mid=(l+r)/2;
if(check(mid)){
r=mid-1;//l=mid+1;
}else{
l=mid+1;//r=mid-1;
}
}cout<<l;//cout<<r;
P2440
题目传送门
思路:
二分最大能切成多长,check(x)来求切成长度为x的时候能切成几段,并与k比较。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<deque>
#include<set>
#include<map>
#define int long long
using namespace std;
int n,k,a[1001100];
bool cmp(int a,int b){
return a>b;
}bool check(int mid){
int cnt=0;
for(int i=1;i<=n;i++){
cnt+=a[i]/mid;
}return cnt>=k;
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n,cmp);
int l=1,r=a[1],mid;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){
l=mid+1;
}else{
r=mid-1;
}
}cout<<r;
return 0;
}
P8800
题目传送门
思路:
二分最多等弄几副牌,check(x)来求要弄x张牌需要写几个,再与和m比较。
代码:
#include<iostream>
#include<algorithm>
#define int long long
using namespace std;
int n,m,a[201000],b[201000];
bool check(int mid){
int sum=0;
for(int i=1;i<=n;i++){
if(a[i]+b[i]<mid)return false;
if(a[i]<mid){
sum+=mid-a[i];
}
}return sum<=m;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}for(int i=1;i<=n;i++){
cin>>b[i];
}int l=0,r=2000000000,mid;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){
l=mid+1;
}else{
r=mid-1;
}
}cout<<r;
return 0;
}
P1577
题目传送门
思路:
1.整数二分:
小数二分不好做,先乘100变成正数进行二分,最后输出时再转成小数,其他思路基本和P2440相同。
2.小数二分:
小数二分不好加一减一,所以直接等于mid,l和r的距离小于一个极小值即可。
小数二分模板:
const double eps=1e-8;
bool check(double mid){
}
double l=???,r=???;
while(r-l>eps){
double mid=(l+r)/2;
if(check(mid))r=mid;//l=mid;
else l=mid;//r=mid;
}
完整代码(整数二分):
#include<iostream>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<deque>
#include<set>
#include<map>
#define int long long
using namespace std;
int n,k;
int a[10200];
bool check(int mid){
int cnt=0;
for(int i=1;i<=n;i++){
cnt+=a[i]/mid;
}if(cnt<k)return false;
return true;
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
double b;
cin>>b;
b=b*100;
a[i]=(int)b;
}int l=1,r=10000000,mid;
while(l<=r){
mid=(l+r)/2;
if(check(mid)){
l=mid+1;
}else{
r=mid-1;
}
}cout<<r/100<<"."<<r/10%10<<r%10;
return 0;
}