【打CF,學演算法——三星級】CodeForces 689C Mike and Chocolate Thieves (二分)
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; }