题解
有一些比较显然的规律
1、这个十进制数只有0/1组成
2、10^k在二进制中一定恰好有k个0
如果我们已经算出恰好有k位数的答案
我们怎么递推算有k+1位合法数
首先想到,如果一个符合条件的k位十进制数,它二进制的第k+1位如果是1,那么这个数无论加不加10^(k+1),它都一定不会再是它二进制的后缀了,(加了之后十进制k+1为是1,二进制k+1为是0,不加的会就相反),所以就可以它在未来都不可能更新答案了
否则,如果是0,加了之后就可以构成一个新的答案,把这个答案保留下来,到下一轮去判断它能不能继续更新k+2位
代码:(十进制由于只有0和1,所以可以也存为二进制)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
bitset<505> p2,p10,ze;
vector<bitset<505> > f,tf,g,tg;
int n,m,cnt;
bitset<505> operator + (bitset<505> x, bitset<505> y)
{
bitset<505> tmp;bool t=0;int tt;
for(int i=0;i<505;i++){
tt=int(x[i])+int(y[i])+int(t);
tmp[i]=tt&1;if(tt>1)t=1;else t=0;
}
return tmp;
}
void write(bitset<505> a)
{
int j;
for(j=504;j>=0;j--)if(a[j])break;
for(;j>=0;j--)printf("%d",int(a[j]));
printf("\n");
}
int main()
{
freopen("quiz.in","r",stdin);
freopen("quiz.out","w",stdout);
int i,k;
scanf("%d",&n);
p2[0]=p10[0]=1;
f.push_back(ze);
g.push_back(ze);
for(k=0;;k++){
m=f.size();
tf.clear();tg.clear();
for(i=0;i<m;i++)if(!g[i][k]){
tf.push_back(f[i]);
tg.push_back(g[i]);
}
for(i=0;i<m;i++)if(!g[i][k]){
tf.push_back(f[i]|p2);
tg.push_back(g[i]+p10);
cnt++;
if(cnt==n){
write(tf[tf.size()-1]);
return 0;
}
}
f.swap(tf);g.swap(tg);
p2<<=1;p10=(p10<<3)+(p10<<1);
}
}