Stringer
.
.
题意:已知有n中字母以及每种字母的个数,问第k大的序列是什么
.
.
解法:每个位置都进行从小到大枚举,看放该字母后面能否到达k,可以就放即可。
.
.
队友代码
#include <cstdio>
#include <cstring>
long long c[51][51];
char ans[1000];
int a[50];
long long k;
int main()
{
c[0][0] = c[1][0] = c[1][1] = 1;
for (int i = 1; i <= 50; i++)
{
c[i][0] = c[i][i] = 1;
for (int j = 1; j < i; j++) c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
int n;
while (~scanf("%d %lld", &n, &k))
{
if (n + k == 0) return 0;
int sum = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
sum += a[i];
}
memset(ans, 0, sizeof(ans));
long long tot = 0;
for (int i = 1; i <= sum; i++)
{
tot = 0;
int j;
long long qqq = 0;
for (j = 1; j <= n; j++)
{
if (a[j] > 0)
{
long long q = c[sum - i][a[j] - 1];
long long s = sum - i - a[j] + 1;
for (int k = 1; k <= n; k++)
{
if (k != j)
{
q *= c[s][a[k]];
s -= a[k];
}
}
qqq = tot;
tot = tot + q;
}
// printf("%d %d %d\n", i,j,tot);
if (tot > k) break;
}
--a[j];
k = k - qqq;
//printf("i:%d j:%d k:%d\n", i, j, k);
ans[i] = 'a' + j - 1;
/*for (int j = 1; j <= n; j++) printf("%d: %d ", j, a[j]);
printf("\n");*/
}
for (int i = 1; i <= sum; i++) printf("%c", ans[i]);
printf("\n");
}
}