Santa Claus and Tangerines

Santa Claus and Tangerines

题目链接:http://codeforces.com/contest/752/problem/E

二分

显然直接求答案并不是很容易,于是我们将其转化为判定性问题:二分解x,验证是否能分成k个x。

于是要点就在于check函数:

由于奇偶的原因,每个ai分出来的并不是2的幂次(比如当ai=11,x=3时,可以将ai分成3部分5,3,3)。

但是稍作思考,可以发现还是与2的幂次有关:

例如,当ai=6:48,x=3时,

ai part1 part2 num
6 3 3 2
       
10 5 5 2
11 5 6 3
12 6 6 4
       
20 10 10 4
21 10 11 5
22 11 11 6
23 11 12 7
24 12 12 8
       
40 20 20 8
41 20 21 9
42 21 21 10
43 21 22 11
44 22 22 12
45 22 23 13
46 23 23 14
47 23 24 15
48 24 24 16

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

若ai=44,因为40<=ai<=48,故num=16-(48-ai);

若ai=38,因为24<=ai<40,故num=8.

 

这种做法的时间复杂度为O(n×lgA×lglgA)

代码如下:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define N 1000005
 4 using namespace std;
 5 typedef long long ll;
 6 ll n,k,a[N],p[28];
 7 void init(){
 8     p[0]=1;
 9     for(ll i=1;i<28;++i)
10         p[i]=p[i-1]<<1;
11 }
12 bool check(ll x){
13     if(!x)return 0;
14     ll sum=0;
15     for(ll i=0;i<n;++i){
16         ll t=a[i]/x;
17         ll up=*upper_bound(p,p+27,t);
18         if(up*x-up/2<=a[i])sum+=up-(up*x-a[i]);
19         else sum+=up/2;
20     }
21     return sum>=k;
22 }
23 int main(void){
24     scanf("%I64d%I64d",&n,&k);
25     init();
26     for(ll i=0;i<n;++i)scanf("%I64d",a+i);
27     ll l=0,r=10000001,mid;
28     while(l+1<r){
29         mid=(r-l)/2+l;
30         if(check(mid))l=mid;
31         else r=mid-1;
32     }
33     if(check(r))printf("%I64d\n",r);
34     else if(check(l))printf("%I64d\n",l);
35     else printf("-1\n");
36 }

 

posted @ 2016-12-26 01:22  barriery  阅读(185)  评论(0编辑  收藏  举报