[2019 Shanghai network F match title] Rhyme scheme

Topic Link

Question is intended to determine the legal length n lexicographically small string of k, is defined as a legitimate except the last one, each bit in the range 'A' to 'A' + pos-1, and the last in a range 'a' to a maximum current string of +1.

Teammate tql, Orz

Outset burst search, but do not know how to determine the current position is legitimate when the number of strings of X. Then his teammates Mang passed Orz.

Roughly approach is similar to the digital pre-dp way how many legitimate string bit i have to j, you can directly determine the ability to meet this demand when the k-th answer, meet to continue the search continues, it does not satisfy the k-dp [i] [j].

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef __int128 ll;
 4 const int mod = 1e9 + 7;
 5 ll dp[30][30];
 6 int ans[30];
 7 int n; ll k;
 8 ll read() {
 9     ll x = 0, f = 1;
10     char c = getchar();
11     for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
12     for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
13     return x * f;
14 }
15 ll dfs(int pos, int limit) {
16     if (pos == n + 1)return 1;
17     if (dp[pos][limit] != -1)return dp[pos][limit];
18     ll sum = 0;
19     for (int i = 0; i <= limit; i++)
20         sum += dfs(pos + 1, max(limit, i + 1));
21     dp[pos][limit] = sum;
22     return dp[pos][limit];
23 }
24 void solve(int pos, int limit, ll k) {
25     if (pos == n) {
26         for (int i = 0; i < n; i++)
27             printf("%c", ans[i] + 'A');
28         printf("\n");
29         return;
30     }
31     for (int i = 0; i <= limit; i++) {
32         ll lim = max(limit, i + 1);
33         if (dp[pos + 1][lim] >= k) {
34             ans[pos] = i;
35             solve(pos + 1, lim, k);
36             break;
37         }
38         else
39             k -= dp[pos + 1][lim];
40     }
41 }
42 int main() {
43     int t, cnt = 1;
44     scanf("%d", &t);
45     while (t--) {
46         scanf("%d", &n);
47         k = read();
48         for (int i = 0; i <= 26; i++)
49             for (int j = 0; j <= 26; j++)
50                 dp[i][j] = -1;
51         for (int i = 0; i < 30; ++i) dp[n][i] = 1;
52         dfs(0, 0);
53         printf("Case #%d: ", cnt++);
54         solve(0, 0, k);
55     }
56 }

 

Guess you like

Origin www.cnblogs.com/sainsist/p/11525638.html