【SSL 1473】奶牛编号
题目大意:
求字典序第 \(N\) 大的只含 \(k\) 个 1 的 01 串。
正文:
考虑到用组合数,由于首位一定是 1,那么我们需要选择位置的 1 就只有 \(k-1\) 个,枚举 01 串长度 \(len\),长度为 \(len\) 的 01 串个数是 \(C_{len}^{k-1}\),每次枚举的时候用 \(N\) 减去。最后得到终点长度 \(len\),只需要求第 \(N\) 大了,暴力求即可。
代码:
void work(int len, int n)
{
for (int i = len - k + 1; i <= len; i++) a[i] = 1;
n--;
while (n--)
{
int tot = 0, i;
for (i = len; i >= 1; i--)
if (a[i])
break;
for (; i >= 1; i--)
{
if (!a[i])
break;
tot++;
}
for (int j = len; j >= i; j--) a[j]=0;
for (int j = len; j >= len - tot + 2; j--)
a[j] = 1;
a[i] = 1;
}
for (int i = 1; i <= len; i++) printf("%d", a[i]);
}
int main()
{
scanf ("%d%d", &n, &k);
C[0][0] = 1ll;
for (int i = 1; i <= N - 10; i++)
{
C[i][0] = 1ll;
for (int j = 1; j <= N - 10; j++)
C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
putchar(49);
if(k == 1)
{
for (int i = 1; i < n; i++)
putchar(48);
puts("");
return 0;
}
int len;
for (len = k - 1; C[len][k - 1] < n; n -= C[len][k - 1], len++)
{
if(len == 2333){
len = 2000;
}
}
k--;
work(len, n);
return 0;
}