Codeforces 1511D. Min Cost String(构造)

传送门


题目描述

给出一个字符串 s s s,若其两个位置 i , j ( i < j < n ) i, j(i < j < n) i,j(i<j<n)满足 a i = a j    & &    a i + 1 = a j + 1 a_i = a_j ~~\&\&~~ a_{i+1} = a_{j+1} ai=aj  &&  ai+1=aj+1那么会对该字符串的价值加一,给定 n , k n,k n,k,仅适用前 k k k个字符构造一个长度为 n n n的字符串使得价值最小。

解题思路

这题过的人不少,自己没过的主要原因是没有研究好样例,实际上样例一给出的就是正确构造方式,而我没有研究样例导致一个多小时也没找到正确的构造方式。

在仔细观察后我们可以发现只需要构造出一个最长的0贡献的字符串,然后不断循环它直到长度到达 n n n。可用的对数实际上只有 k ∗ k k*k kk对,所以后面出现的每对一定都会产生贡献,为了贡献最小,以这样的方式。具体参考了学长的证明:找到的最长0贡献字符串长度是len,我们把len看作一个周期,那么在下一个周期当中,让贡献速度增加最慢的方式就是让上个周期的每一个相邻位置(记为 p a i r pair pair )都出现唯一一次。在第一个周期中大约有 l e n 2 \frac{len}{2} 2len个pair,第二个周期中每个 p a i r pair pair 都多出现了仅1次,那么贡献就是大约 l e n 2 \frac{len}{2} 2len,如果某个 p a i r pair pair 多出现了一次,另一个 p a i r pair pair 少出现了一次,那么总贡献会更糟糕。

画出一个 k ∗ k k*k kk的矩阵时可以发现 a   a b   a c   ⋅ ⋅ ⋅   a z   b   b c   ⋅ ⋅ ⋅   b z   c . . . a~ab~ac~···~az~b~bc~···~bz~c... a ab ac  az b bc  bz c...这样的构造方式确实是比较容易的构造方式。以后的构造题一定要好好研究样例

#include <bits/stdc++.h>

using namespace std;
#define ENDL "\n"
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int Mod = 1e9 + 7;
const int maxn = 3e5 + 15;

int a[26][26];

int main() {
    
    
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m;
    cin >> n >> m;
    string s = "";
    while (1) {
    
    
        for (int i = 0; i < m; i++) {
    
    
            char cur = 'a' + i;
            s += cur;
            n--;
            if (n == 0) goto done;
            for (int j = i + 1; j < m; j++) {
    
    
                s += cur;
                n--;
                if (n == 0) goto done;
                s += 'a' + j;
                n--;
                if (n == 0) goto done;
            }
        }
    }
done:
    cout << s << ENDL;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/115680136
今日推荐