码迷,mamicode.com
首页 > 其他好文 > 详细

尽力日更_CF上的构造题

时间:2021-04-15 12:44:35      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:最小   abc   pen   force   for   adb   space   play   alt   

由于B,C题总是过得太慢甚至做不出来,特开此帖进行训练.

现在的想法是每天一道1600的题目.

 

D. Min Cost String

给出一个长度n与字符集为前k个英文字母,要求构造出一个长度为n的字符串,使得其中的cost最小.

cost定义为满足si=sj且si+1=sj+1的索引对i,j的数量.(1<=i<j<n)

 

首先,cost可以更直观地定义为满足sisi+1=sjsj+1的子串数量.

注意,如果有三这样的子串,那么子串对的数量是C32=3个.即x个相同子串可构成Cx2个不同的子串对.

 

可以得出在给定的大小为k的字符集中,最多有k2个不同的子串,因此可以先构造出一个长度最长为k2+1的字符串,其中每一种子串都出现一次,cost=0.

如,取k=4,可得:

aabacadbbcbdccdda
长度为17

之后,每增加一个字符就会使得某种子串的数量增加1,现在需要找出一种策略使得cost的增长速度最慢.

很容易会想到:

aabacadbbcbdccdda bcdabcdabcdabcd...

然后WA了.

 

思考之后,发现根据组合数的增长性质,应该让所有子串的数量依次增加,而不是让某个子串的数量成为峰值.

因此有:

aabacadbbcbdccdda abacadbbcbdccdda abacadbbcbdccdda ...

 

技术图片
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;

int n, k;
string ans;
string s = "0abcdefghijklmnopqrstuvwxyz";

int main(){
    cin >> n >> k;

    for(int i = 1; i < k; i++){
        ans.push_back(s[i]);
        for(int j = i + 1; j <= k; j++){
            ans.push_back(s[i]);
            ans.push_back(s[j]);
        }
    }
    ans.push_back(s[k]);
    int sz = ans.size();
    while(ans.size() < n) ans += ans.substr(0, sz);

    cout << ans.substr(0, n) << endl;

    return 0;
}
D. Min Cost String

 

尽力日更_CF上的构造题

标签:最小   abc   pen   force   for   adb   space   play   alt   

原文地址:https://www.cnblogs.com/Gaomez/p/14660890.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!