POj3104 二分

题面:

                        (1):对于每个K,我们可以知道的是如果有两件衣服都需要风干,无论用于每台机子都是可以的。

                        (2):我们接下来想最少需要多少时间,这个如果我们想直接算出答案的话,是接近不可能的,因为你没有什么好的贪心算来确定到底把洗衣机用于那台机器上面,这个是个很麻烦的事情,这样就意味着我们不能直接挣正面做

                        (3):不能正面做就侧面做??????????(为什么要这样搞,我也不知道)

                        (4):显然这玩意满足二分性质,我时间越多我就越能完成

                        (5):接下来就怎么check了,这个check比较好像,就直接考虑这台机器能不能在指定时间内完成,能的话就不用洗衣机,不能的话就用洗衣机。接下来这样搞了一遍后就挺ok的了。然后我们看洗衣机的占用时间是不是小于这个时间,如果可以的话,我们就true

                      (6):然后就是二分的套路了

                        (7):最重要的是check里面那个公式,关于洗衣机和自动洗衣的时间怎么分配,假设分s1秒给洗衣机   num[i]<=k*s1+(mid-s1)       即要满足  num[i]-mid <=(k-1)*s1   解出这个s1即可。       

                       下面是代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cmath>
 5 #include <bitset>
 6 typedef long long ll;
 7 using namespace std;
 8 const int maxn=101000;
 9 int n;
10 ll k;
11 ll num[maxn];
12 
13 bool check(ll mid){
14     ll ans=0,t;
15     for(int i=1;i<=n;i++){
16         if(num[i]<=mid) continue;
17         //num[i]>mid
18         if(mid*k<num[i]) return false;
19         // num[i] <mid*k
20         //上面的两句话保证了k>1
21 
22         //这个具体是怎么操作的
23         //公式大法好
24         //  num[i] = (k)*s1+(mid-s1)
25         //  num[i] = (k-1)*s1  +mid  ->  num[i]-mid  = (k-1) *s1;
26         t=num[i]-mid;
27         if(t%(k-1)==0)  ans+=(t/(k-1));
28         else ans=(ans+1+(t/(k-1)));
29     }
30     return ans<=mid;
31 }
32 
33 int main(){
34     scanf("%d",&n);
35     ll lb=1,rb=1,ans=1;
36     for(int i=1;i<=n;i++){scanf("%lld",&num[i]);rb=max(num[i],rb);}
37     scanf("%lld",&k);
38     while(lb<=rb){
39         ll mid=(lb+rb)/2;
40         if(check(mid)){
41             ans=mid;
42             rb=mid-1;
43         }else lb=mid+1;
44     }
45     printf("%lld
",ans);
46     return 0;
47 }
View Code
原文地址:https://www.cnblogs.com/pandaking/p/12031498.html