标签:最小 abc pen force for adb space play alt
由于B,C题总是过得太慢甚至做不出来,特开此帖进行训练.
现在的想法是每天一道1600的题目.
给出一个长度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; }
标签:最小 abc pen force for adb space play alt
原文地址:https://www.cnblogs.com/Gaomez/p/14660890.html