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\n",ans); 46 return 0; 47 }