问题 A: 滑雪训练
时间限制 : 1.000 sec 内存限制 : 128 MB
题目描述
寒假集训结束了,叶老师组织了同学们去参加滑雪。有n个人依次进入滑雪更衣室,准备换衣服滑雪。
更衣室只有一排座位,第1个人进入时,会选择第1个座位坐下。
之后的每个人进入时,他会选择一个离最近的已经坐下的人尽可能远的空位。
如果有多个空位使得离最近的人同样远,则他会从其中随机选取一个。
若有两个人选择的位置相邻,他们就会不满意。
为了让所有人都满意,更衣室至少需要有几个座位呢?
输入
包含一行,仅一个正整数n
,表示前来滑雪的人数。
输出
包含一行,仅一个正整数,表示至少需要的座位数目。
样例输入 Copy
4
样例输出 Copy
8
提示
更衣室只有7个位置时,前3个人会依次选择1,7,4 这3个位置,第4个人无论选哪个空位,都会与其他人相邻。
更衣室有8个位置时,他们依次选取的位置可能是 1 8 4 6 与 1 8 5 3 两种情况,都是合法的。
10% n<=5
另20% n<=10^5
另20% n<=10^18
所有n<=10^1000
思路
注意到 ans=2^q+n
,且满足2^q
恰好大于等于n-1
推出这样的公式后,只要找到使2^q>=n-1
恰好成立的2^q
即可
这里给出几组数据
n=1,ans=1;
n=2,ans=3;
n=3,ans=5;
4,8;
5,9;
6,14;
7,15;
8,16;
9,17;
10,26;
AC
代码
//#pragma GCC optimize(2)
//clock_t st=clock();
#include<bits/stdc++.h>
using namespace std;
string prec_plus(string plus_s1,string plus_s2){
int plus_i1[10100],plus_i2[10100];
int l1=plus_s1.length(),l2=plus_s2.length();
string ans="";
int len=max(l1,l2);
memset(plus_i1,0,sizeof(plus_i1));
memset(plus_i2,0,sizeof(plus_i2));
for(int i=l1-1;i>=0;i--)
plus_i1[l1-i-1]=plus_s1[i]-'0';
for(int i=l2-1;i>=0;i--)
plus_i2[l2-i-1]=plus_s2[i]-'0';
for(int i=0;i<len;i++){
plus_i1[i]+=plus_i2[i];
plus_i1[i+1]+=plus_i1[i]/10;
plus_i1[i]%=10;
}
if(plus_i1[len]!=0) len++;
while(plus_i1[len-1]==0 and len>1)
len--;
for(int i=len-1;i>=0;i--)
ans=ans+char(plus_i1[i]+'0');
return ans;
}
string prec_minus(string minus_s1,string minus_s2){
int minus_i1[10100],minus_i2[10100];
int l1=minus_s1.length(),l2=minus_s2.length();
string ans="";
int len=max(l1,l2);
memset(minus_i1,0,sizeof(minus_i1));
memset(minus_i2,0,sizeof(minus_i2));
for(int i=l1-1;i>=0;i--)
minus_i1[l1-i-1]=minus_s1[i]-'0';
for(int i=l2-1;i>=0;i--)
minus_i2[l2-i-1]=minus_s2[i]-'0';
for(int i=0;i<len;i++){
minus_i1[i]-=minus_i2[i];
if(minus_i1[i]<0){
minus_i1[i]+=10;
minus_i1[i+1]--;
}
}
while(minus_i1[len-1]==0 and len>1)
len--;
for(int i=len-1;i>=0;i--)
ans=ans+char(minus_i1[i]+'0');
return ans;
}
string prec_multiply(string multiply_s1,string multiply_s2){
int multiply_i1[1010],multiply_i2[1010],multiply_i3[1010];
int l1=multiply_s1.length(),l2=multiply_s2.length();
string ans="";
int len=(l1+l2);
memset(multiply_i1,0,sizeof(multiply_i1));
memset(multiply_i2,0,sizeof(multiply_i2));
memset(multiply_i3,0,sizeof(multiply_i3));
for(int i=l1-1;i>=0;i--)
multiply_i1[l1-i-1]=multiply_s1[i]-'0';
for(int i=l2-1;i>=0;i--)
multiply_i2[l2-i-1]=multiply_s2[i]-'0';
for(int i=0;i<l1;i++){
for(int j=0;j<l2;j++){
multiply_i3[i+j]+=multiply_i1[i]*multiply_i2[j];
multiply_i3[i+j+1]+=multiply_i3[i+j]/10;
multiply_i3[i+j]%=10;
}
}
while(multiply_i3[len-1]==0 and len>1)
len--;
for(int i=len-1;i>=0;i--)
ans=ans+char(multiply_i3[i]+'0');
return ans;
}
bool cmp_str(string x1,string x2){//x1>=x2
if(x1==x2) return true;
else if(x1.length()!=x2.length()) return x1.length()>x2.length();
else return x1>x2;
}
//ans=2^q+n,2^q>=n-1
int main(){
string n;
cin>>n;
if(n=="1") {cout<<1;exit(0);}
string m=prec_minus(n,"1");//m=n-1
string num="1";//num=2^0=1
while(!cmp_str(num,m)){
num=prec_multiply(num,"2");
}//num=2^q
string ans=prec_plus(num,n);//ans=num+n
cout<<ans;
return 0;
}