1. 程式人生 > >【打CF,學演算法——三星級】CodeForces 689C Mike and Chocolate Thieves (二分)

【打CF,學演算法——三星級】CodeForces 689C Mike and Chocolate Thieves (二分)

Note

In the first sample case the smallest n that leads to exactly one way of stealing chocolates isn = 8, whereas the amounts of stealed chocolates are(1, 2, 4, 8) (the number of chocolates stolen by each of the thieves).

In the second sample case the smallest n that leads to exactly8 ways is n = 54 with the possibilities:(1, 2, 4, 8),  (1, 3, 9, 27),  (2, 4, 8, 16),  (2, 6, 18, 54),  (3, 6, 12, 24),  (4, 8, 16, 32),  (5, 10, 20, 40),  (6, 12, 24, 48)

.

There is no n leading to exactly 10 ways of stealing chocolates in the third sample case.

題意:

    給定一個數字n,問能不能求得一個最小的整數x,使得在1-x範圍內,可以取的n組T*k^3<=x。T,k為任意整數,需要在小於等於x的情況下,湊夠n對T,k,使其滿足T*k^3<=x。若x存在,則輸出x,若x不存在,則輸出-1。

解題:

     解題的大致流程是這樣的。

     先看k=2,(1,2,4,8)/(2,4,8,16)/(3,6,12,24)....

            k=3,(1,3,9,27)/(2,6,18,54)......

            對應某個k,在x範圍內,其能取到的最大組數為x/(k^3),因為合法組數具有單調性,可以採用二分的方法求解。

     兩種情況很好理解,噹噹前數量已大於要求數量,那便移動右邊界,噹噹前數量小於要求數量,則移動左邊界,但相等時,並不一定就是解。因為,題目要求是合法時最小的整數解,故而繼續移動右邊界。

程式碼:

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long
using namespace std;
LL time3[1000001];
int main()
{
	bool flag=0;
	LL le=1,ri=1e18,mid,lim,cnt,m,ans;
    for(int i=0;i<1000001;i++)
    {
		time3[i]=1;
		time3[i]=1LL*i*i*i;
	}
	cin>>m;
    while(le<=ri)
	{
      mid=(le+ri)>>1;
      lim=pow(1.0*mid,1.0/3)+1;
	  cnt=0;
	  for(int i=2;i<=lim;i++)
	  {
        cnt+=mid/time3[i];
	  }
	  if(cnt>m)
		  ri=mid-1;
	  else if(cnt<m)
		  le=mid+1;
	  else
	  {
		  flag=1;
		  ans=mid;
		  ri=mid-1;
	  }
	}
	if(flag)
		cout<<ans<<endl;
	else
		cout<<"-1\n";
	return 0;
}