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 ",r); 34 else if(check(l))printf("%I64d ",l); 35 else printf("-1 "); 36 }