A rhyme scheme is the pattern of rhymes at the end of each line of a poem or song. It is usually referred to by using letters to indicate which lines rhyme; lines designated with the same letter all rhyme with each other.
e.g., the following "poem'' of 44 lines has an associated rhyme scheme "ABBA''
1 —— 9999 bugs in the code A
2 —— Fix one line B
3 —— Should be fine B
4 —— 100100 bugs in the code A
This essentially means that line 11 and 44 rhyme together and line 22 and 33 rhyme together.
The number of different possible rhyme schemes for an nn-line poem is given by the Bell numbers. For example, B_3 = 5B3=5, it means there are five rhyme schemes for a three-line poem: AAA, AAB, ABA, ABB, and ABC.
The question is to output the kk-th rhyme scheme in alphabetical order for a poem of nn lines.For example: the first rhyme scheme of a three-line poem is "AAA'', the fourth rhyme scheme of a three-line poem is ABB''.
The first line of the input gives the number of test cases, TT (1 \leq T \leq 100001≤T≤10000). TT test cases follow.
Each test case contains a line with two integers nn and kk.
1 \leq n \leq 26, 1 \leq k \leq B_n1≤n≤26,1≤k≤Bn (B_nBn is the nn-th of Bell numbers)
For each test case, output one line containing Case #x: y, where xx is the test case number (starting from 11) and yy is the rhyme scheme contains uppercase letters.
样例输入复制
7 1 1 2 1 3 1 3 2 3 3 3 4 3 5
样例输出复制
Case #1: A Case #2: AA Case #3: AAA Case #4: AAB Case #5: ABA Case #6: ABB Case #7: ABC
预处理出dp数组,dp[i][j]表示现在字符串中字母种类有i种,再放j个字母后的所有可能个数有多少。
然后进行dfs,尝试去放这i种字母,还是放第i+1种字母。
因为贝尔数第26位超过了longlong的界限,所以我自己写了之后让队友改的Java。
我的:
#include
using namespace std;
string ans = "";
long long dp[27][27];
void dfs(int sum, int len) {
if (dp[sum][len] != -1)
return;
if (len == 0) {
dp[sum][len] = 1;
return;
}
dfs(sum, len - 1); dfs(sum + 1, len - 1);
dp[sum][len] = (sum)* dp[sum][len - 1] + dp[sum + 1][len - 1];
}
void check(int zl, int len, long long k) {
if (len == 0)return;
if (k > (zl)* dp[zl][len - 1]) {
ans += ('A' + zl);
check(zl + 1, len - 1, k - (zl)* dp[zl][len - 1]);
}
else {
long long res = 0;
for (int i = 0; i < zl; i++) {
if (k <= res + dp[zl][len - 1]) {
ans += ('A' + i);
check(zl, len - 1, k - res);
break;
}
res += dp[zl][len - 1];
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int te; cin >> te; int cas = 1;
memset(dp, -1, sizeof dp);
dfs(0, 26);
while (te--) {
long long k; int n;
cin >> n >> k;
ans = "";
check(0, n, k);
cout << "Case #" << cas << ": " << ans << "\n"; cas++;
}
return 0;
}
让队友改的:
import java.math.BigInteger;
import java.util.*;
public class Main {
public static BigInteger[][] dp = new BigInteger[27][27];
public static String ans;
public static void main(String[] args) {
for (int i = 0; i < 27; ++i) {
for (int j = 0; j < 27; ++j) {
dp[i][j] = BigInteger.valueOf(-1);
}
}
dfs(0, 26);
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
int cas = 1;
while (t-- != 0) {
int n = sc.nextInt();
BigInteger k = sc.nextBigInteger();
ans = "";
check(0, n, k);
System.out.println("Case #" + cas + ": " + ans);
cas++;
}
}
public static void dfs (int sum, int len) {
if (dp[sum][len].compareTo(BigInteger.valueOf(-1)) != 0) {
return ;
}
if (len == 0) {
dp[sum][len] = BigInteger.ONE;
return ;
}
dfs(sum, len-1);
dfs(sum+1, len-1);
dp[sum][len] = (dp[sum][len-1].multiply(BigInteger.valueOf(sum))).add(dp[sum+1][len-1]);
}
public static void check (int zl, int len, BigInteger k) {
if (len == 0) {
return ;
}
if ((k.subtract((BigInteger.valueOf(zl)).multiply(dp[zl][len-1]))).compareTo(BigInteger.ZERO) > 0) {
ans = ans+(char)('A'+zl);
check(zl + 1, len - 1, k.subtract((BigInteger.valueOf(zl)).multiply(dp[zl][len-1])));
}
else {
BigInteger res = BigInteger.ZERO;
for (int i = 0; i < zl; i++) {
if ((k.subtract(res)).compareTo(dp[zl][len-1]) <= 0) {
ans = ans+(char)('A'+i);
check(zl, len-1, k.subtract(res));
break;
}
res = res.add(dp[zl][len-1]);
}
}
}
}