题目描述
牛牛和妞妞去海边捡了一大袋美丽的贝壳,千辛万苦地运回家后,牛牛和妞妞打算分掉这些贝壳。
牛牛提出,他和妞妞轮流从还没有分配的贝壳中取一定数量的贝壳,直到贝壳分完为止。分配规则是牛牛每次取剩余贝壳的1/10(向下取整),妞妞每次固定取m个贝壳,妞妞先取。
妞妞想要得到不少于一半的贝壳,又不想太过分,那么她一次最少取多少个贝壳才能得到不少于一半的贝壳呢?
输入描述:
一个正整数n,表示贝壳的总数量,1<=n<=1000000000000000000。
输出描述:
一个正整数m,表示妞妞一次最少取的贝壳数量。
示例1
输入
10
输出
1
示例2
输入
70
输出
3
思路
在二分查找中,调用函数find(int m,int n),m为妞妞每次固定拿的个数,n为总的贝壳数,find(int m,int n)为按照规定开始拿贝壳,返回妞妞拿到的贝壳数。
要求妞妞每次拿的贝壳数不能太多,但总数要不少于一半的贝壳,那么只要这个贝壳数大于等于总数,就对妞妞每次应该拿的贝壳数更新,那么就能保证她每次能以最小的数量拿不少于一般的贝壳。
#include<iostream>
#include<cstring>
using namespace std;
long long find(long long m,long long n){
long long girl=0;
while(n){
if(m<=n){
n-=m;
girl+=m;
}
else{
girl+=n;
return girl;
}
if(n>=10)
n-=n/10;
}
}
int main(){
long long n,mid,min,th,left,right;
cin>>n;
left=1;
right=n;//1>n/10?1:n/10;
min=right;
th=n;
long long newmid;
while(left<=right){
mid=(left+right)/2;
newmid=find(mid,n);
if(newmid>=(n+1)/2)//如果女孩的贝壳大于总数的一半,说明女孩可以取到贝壳的一半以上
{
if(newmid<th)//此时比较最大贝壳数目,留下每次贝壳数目最小的
{
th=newmid;
min=mid;
}
right=mid-1;
}
else left=mid+1;
}
cout<<min;
return 0;}
当right被初始化为right=1>n/10?1:n/10;时,就已经保证妞妞拿的贝壳数不少于总数的一半了,因为当女孩以n/10的数量拿,总数不会比牛牛拿的少。
PS :
- 当以顺序查找时,超时。
- 注意数据类型为long long,否则当数据太大,输出不了结果。