对于一个合法的十进制数,它的所有后缀也是合法的。
于是按位BFS,保留前导零,每次往前添加一个$0$或者$1$,直到找到第$n$个不含前导零的合法数为止即可。
时间复杂度$O(nl)$。
#include<cstdio>
#define N 400
struct Num{
int len,v[N];
Num(){for(int i=len=1;i<N;i++)v[i]=0;}
Num operator+(const Num&b){
Num c;
c.len=b.len+1;
for(int i=1;i<=c.len;i++)c.v[i]=v[i]+b.v[i];
for(int i=1;i<=c.len;i++)c.v[i+1]+=c.v[i]>>1,c.v[i]&=1;
while(!c.v[c.len])c.len--;
return c;
}
Num operator*(const Num&b){
Num c;
c.len=len+b.len;
for(int i=1;i<=len;i++)for(int j=1;j<=b.len;j++){
if(i+j-1>=N)break;
c.v[i+j-1]+=v[i]*b.v[j];
}
for(int i=1;i<=c.len;i++)c.v[i+1]+=c.v[i]>>1,c.v[i]&=1;
while(!c.v[c.len])c.len--;
return c;
}
}Ten,Pow,y;
struct Big{int len,v[N];Big(){len=0;for(int i=1;i<N;i++)v[i]=0;}}x;
struct P{Big x;Num y;P(){}P(Big _x,Num _y){x=_x,y=_y;}}q0[2][210],q1[2][210];
int t0[2],t1[2],n,i,j,k,o;
inline bool check(int x,Big d,Num b){
for(int i=1;i<=x;i++)if((i<=d.len?d.v[i]:0)!=(i<=b.len?b.v[i]:0))return 0;
return 1;
}
int main(){
Ten.v[2]=Ten.v[4]=1,Ten.len=4;
Pow.v[1]=1;
scanf("%d",&n);
q0[0][t0[0]=1]=P(Big(),Num());
for(i=1;;i++,o^=1,Pow=Pow*Ten){
t0[o^1]=t1[o^1]=0;
for(j=1;j<=t0[o];j++){
x=q0[o][j].x,y=q0[o][j].y;
if(check(i,x,y))q0[o^1][++t0[o^1]]=P(x,y);
x.len=i,x.v[i]=1,y=y+Pow;
if(check(i,x,y)){
if(!(--n)){
for(k=i;k;k--)putchar(x.v[k]+‘0‘);
return 0;
}
q1[o^1][++t1[o^1]]=P(x,y);
}
}
for(j=1;j<=t1[o];j++){
x=q1[o][j].x,y=q1[o][j].y;
if(check(i,x,y))q0[o^1][++t0[o^1]]=P(x,y);
x.len=i,x.v[i]=1,y=y+Pow;
if(check(i,x,y)){
if(!(--n)){
for(k=i;k;k--)putchar(x.v[k]+‘0‘);
return 0;
}
q1[o^1][++t1[o^1]]=P(x,y);
}
}
}
return 0;
}
BZOJ4404 : [Neerc2015]Binary vs Decimal
原文:http://www.cnblogs.com/clrs97/p/5156438.html