思路1:

每次贪心地选择满足i * (i - 1) / 2 <= k最大的i并从k中减去i * (i - 1) / 2,直至k为0。由于函数x * (x - 1) / 2的增长速度比2x要慢,所以这种方法的收敛速度比每次减掉某个2的幂还要快一些,26个小写字母是肯定够用的。

实现:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int k;
 6     cin >> k;
 7     for (char c = 'a'; c <= 'z'; c++)
 8     {
 9         int i = 1;
10         while (i * (i - 1) / 2 <= k) i++;
11         k -= (i - 1) * (i - 2) / 2;
12         for (int j = 1; j < i; j++) cout << c;
13     }
14     return 0;
15 }

思路2:

完全背包+恢复路径。

与贪心方法相比,这种方法可以找到使用最少字母种类的方案。

注意恢复路径的方法。

实现:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[1005], inv[100005], ans[1005], dp[100005], path[100005];
 4 int main()
 5 {
 6     int k;
 7     cin >> k;
 8     if (!k) { cout << "a"; return 0; }
 9     int i = 1;
10     memset(dp, 0x3f, sizeof dp);
11     memset(path, 0, sizeof path);
12     dp[0] = 0; path[0] = -1;
13     for ( ; i * (i - 1) <= 2 * k; i++) 
14     { 
15         a[i] = i * (i - 1) >> 1; 
16         inv[i * (i - 1) >> 1] = i;
17     }
18     for (int j = 2; j < i; j++)
19     {
20         for (int p = a[j]; p <= k; p++)
21         {
22             if (dp[p - a[j]] + 1 < dp[p])
23             {
24                 dp[p] = dp[p - a[j]] + 1;
25                 path[p] = p - a[j];
26             }
27         }
28     }
29     while (path[k] != -1) { ans[inv[k - path[k]]]++; k = path[k]; }
30     char now = 'a';
31     for (int j = 2; j < i; j++) 
32     {
33         if (ans[j]) 
34         { 
35             for (int x = 0; x < ans[j]; x++)
36             {
37                 for (int p = 0; p < j; p++) cout << now;
38                 now++;
39             }
40         }
41     }
42     return 0;
43 }

 

相关文章:

  • 2021-09-26
  • 2022-12-23
  • 2022-12-23
  • 2021-05-15
  • 2021-04-30
  • 2021-07-14
  • 2021-12-20
  • 2021-08-11
猜你喜欢
  • 2022-12-23
  • 2021-08-07
  • 2022-12-23
  • 2022-12-23
  • 2021-04-26
  • 2021-08-05
  • 2022-01-15
相关资源
相似解决方案