http://codevs.cn/problem/5118/
题目描述 Description
Wjj又给她的妹子们拍了很多视频。为了拍摄这些视频,并保证视频的清晰度,让每一根毛都能看得清清楚楚,他还特意去买了一张32TB的内存卡。
当Wjj准备用你之前给他写的编号程序给新拍的视频编号时,程序出了错误。
现在,Wjj非常生气,他要你立刻写出正确的程序,并给所有新的视频编好号。
编号的方式和之前相同。第1个视频编号是1;第2、3个视频编号是2,4;第4、5、6个视频编号是5,7,9;接下来四个的编号是10,12,14,16;以此类推。现在Wjj拍摄了n段视频,他要立刻知道第n段视频的编号是多少。
为了尽快看到Wjj拍的视频,你需要写出效率很高的代码来为视频编号,否则就不能欣赏Wjj的作品了。
输入描述 Input Description
输入共一行,一个整数n,表示wjj现在有n段视频
输出描述 Output Description
输出共一行,一个整数,表示第n段视频的编号。
样例输入 Sample Input
【样例输入1】
1
【样例输入2】
4
样例输出 Sample Output
【样例输出1】
1
【样例输出2】
5
数据范围及提示 Data Size & Hint
对于100%的数据,n<10100。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstring>
#define N 5005
#define D 10000
using namespace std;
struct bignum{
int len,x[N];
bignum(int x_=0){x[len=1]=x_;}
bignum(int x_,int y_){for(register int i=1;i<x_;++i)x[i]=0 ;x[len=x_]=y_;}
bignum(char *s);
};
bignum::bignum(char *s)
{
int len_s=strlen(s),cnt=0;
for(int i=len_s-1;i>=0;i-=4)
{
int num=0;
for(register int j=i-3>=0?i-3:0;j<=i;++j) num=num*10+s[j]-'0';
x[++cnt]=num;
}
len=cnt;
}
inline bool operator < (const bignum &a,const bignum &b)
{
if(a.len!=b.len) return a.len<b.len;
for(register int i=a.len;i;--i)
if(a.x[i]!=b.x[i]) return a.x[i]<b.x[i];
return 0;
}
inline bignum operator + (bignum a,bignum b)
{
bignum c;
c.len=max(a.len,b.len);
for(int i=c.len+1;i;--i) c.x[i]=0;
for(int i=a.len+1;i<=c.len;++i) a.x[i]=0;
for(int i=b.len+1;i<=c.len;++i) b.x[i]=0;
for(int i=1;i<=c.len;++i)
if((c.x[i]+=a.x[i]+b.x[i])>=D) c.x[i]-=D,c.x[i+1]++;
if(c.x[c.len+1]) c.len++;
return c;
}
inline bignum operator - (bignum &a,bignum &b)
{
bignum c;
c.len=a.len;
for(int i=c.len;i;--i) c.x[i]=0;
for(int i=b.len+1;i<=c.len;++i) b.x[i]=0;
for(int i=1;i<=c.len;++i)
if((c.x[i]+=a.x[i]-b.x[i])<0) c.x[i]+=D,c.x[i+1]--;
if(a.len>1&&!a.x[a.len]) a.len--;
return c;
}
inline bignum operator * (const bignum &a,const bignum &b)
{
bignum c;
for(register int i=a.len+b.len;i;--i) c.x[i]=0;
for( int i=a.len;i;--i)
for(register int j=b.len;j;--j)
{
c.x[i+j-1]+=a.x[i]*b.x[j];
if(c.x[i+j-1]>=1000000000) c.x[i+j]+=c.x[i+j-1]/D,c.x[i+j-1]%=D;
}
for(register int i=1,t=a.len+b.len;i<t;++i)
if(c.x[i]>=D) c.x[i+1]+=c.x[i]/D,c.x[i]%=D;
if(!c.x[c.len=a.len+b.len]) c.len--;
return c;
}
inline void sub(bignum &a)
{
a.x[1]--;
for( int j=1;a.x[j]<0;++j)
a.x[j+1]--,a.x[j]+=D;
if(a.len>1&&!a.x[a.len]) a.len--;
}
inline bignum sub_r(bignum a)
{
a.x[1]--;
for( int j=1;a.x[j]<0;++j)
a.x[j+1]--,a.x[j]+=D;
if(a.len>1&&!a.x[a.len]) a.len--;
return a;
}
inline bignum add(bignum a)
{
a.x[1]++,a.x[a.len+1]=0;
for( int j=1;a.x[j]>=D;++j)
a.x[j+1]++,a.x[j]-=D;
if(a.x[a.len+1]) a.len++;
return a;
}
inline bignum div2(bignum a)
{
for( int j=a.len;j;--j)
{
if(a.x[j]&1) a.x[j-1]+=D;
a.x[j]>>=1;
}
if(a.len>1&&!a.x[a.len]) a.len--;
return a;
}
void output(const bignum &a)
{
printf("%d",a.x[a.len]);
for(register int i=a.len-1;i;--i) printf("%04d",a.x[i]);
}
int main()
{
freopen("oddeven.in","r",stdin);
freopen("oddeven.out","w",stdout);
char s[N];
scanf("%s",s);
bignum n(s),i(n);
if(n.len==1&&n.x[1]==1) return puts("1"),0;
sub(n);
bignum l(0),r(n);
while(l<sub_r(r))
{
bignum mid=div2(l+r);
bignum t=div2(mid*add(mid));
if(n<t) r=mid;
else l=mid;
}
output((n-l)+i);
return 0;
}