2021.11.23数位dp
作者:
哈密
,
2021-11-23 20:14:34
,
所有人可见
,
阅读 219
比特币1382
#include<bits/stdc++.h>
using namespace std;
const int N=31; //尼玛的这里只能是31
int s[N][N],f[N][N]; //f[i][j]表示当前在第i位(第0位最小),且后面最多有j个1的方案数
int main(){
int n,l,I;
cin>>n>>l>>I;
for(int i=0;i<N;i++){
for(int j=0;j<=i;j++){
if(!j)s[i][j]=1; //Cab=Cab−1+Ca−1b−1 组合数处理
else s[i][j]=s[i-1][j]+s[i-1][j-1];
}
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){ //针对N位就应该按位枚举
for(int k=0;k<=j;k++){
f[i][j]+=s[i][k];
}
}
}
for(int i =1,s=0;i<=n;++i) { // s 表示1的个数
int x= f[n-i][l-s]; // 剩下n - i位, 1 的个数不超过 L - s
if (I>x) {
cout<<1;
I-=x;
++s;
}
else cout << 0;
/*第一位填0还是填1是取决于后N−1位的组合方案数x与k的相比较而得到的。
当 x≥k 时, 就说明在剩下的N−1的组合方案中是包含第k个元素的,则第一位就应该填 0。
当 x<k 时, 就说明在剩下的N−1的组合方案中是不包含第k个元素的,则第一位就应该填1
因为侧面证明只包含在第一位为1的集合中,由此第一位只能为1,
再看第二位时,应该在第一位的基础上进行比较,则 k−=x,剩下的N−2位才能进行比较。*/
}
}