题解

有一些比较显然的规律

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);
	}
}