/* 一开始认为是个水题 直接模拟 没想到只得了50分 一看数据吓niao了 模拟妥妥的TLE 实在不好优化了0.0(最快O(m)) 然后借鉴别人的 DP+神奇的输出 DP:状态:f[i][j] 前i个字符出现j次1的数字个数 很容易想到 如果i是1 f[i][j]=f[i][j]+f[i-1][j-1] 如果i是0 f[i][j]=f[i][j]+f[i-1][j] 初始化 i==0||j==0时 个数为1 然后就是神奇的输出了0.0 看代码吧 */ /* TLE 50 模拟 */ #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int n,l,m,num; int main() { cin>>n>>l>>m; int s=(2<<n-1)-1; for(int i=0;i<=s;i++) { int li=0,x=i,y; while(x>0) { y=x%2; x=x/2; if(y==1)li++; } if(li<=l)num++; if(num==m) { int a[33]={0},li=0; while(i>0) { a[++li]=i%2; i=i/2; } for(int j=n;j>=1;j--) cout<<a[j]; return 0; } } } /* AC 100 DP */ #include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; ll f[33][33],n,l,m; int main() { ll i,j; cin>>n>>l>>m; for(i=0;i<=n;i++)f[i][0]=1; for(i=0;i<=l;i++)f[0][i]=1; for(i=1;i<=n;i++) for(j=1;j<=l;j++) f[i][j]=f[i-1][j]+f[i-1][j-1]; m--;//减掉0的一种情况 for(i=n;i>=1;i--)//枚举位置 if(m&&f[i-1][l]<=m)//输出1的条件:前i-1位中含‘剩余’l的数字个数不超过m并且m>=1 { cout<<1; m=m-f[i-1][l];//与‘目标’还差几 l--;//‘剩余’l的数字个数 } else cout<<0; return 0; }