1 分析题面
珂愛想要知道,她至少需要操作多少次,才能让这个字符串的长度大于等于 L L L。
即每次操作都要选择出现次数最多的字符进行操作。
1.1 坑点
下面给出一组数据:
输入:
llasw
4
输出:
0
这就是坑:当 ∣ S ∣ ≥ L |S|\ge L ∣S∣≥L 时,操作次数为 0 0 0。
开始我没考虑,于是乎:15pts。
1.2 数据范围
1 ≤ L < 2 64 1\le L<2^{64} 1≤L<264
而 unsigned long long
的数据范围刚好是
[
0
,
2
64
)
[0,2^{64})
[0,264)!!!
2 过程
首先需要统计每个字符出现的次数,使用 C++ 中 STL 里的 map 容器可以很便捷地做到。
2.1 map容器的使用
map
: 映射表
#include <map>
:map
头文件。
map <A,B> ds
:建立一个叫ds
的,下标类型为A
,元素类型为B
的映射表。
map[A]
:访问下标为A
的元素。
2.2 "打擂台"比较
然后需要比较出出现次数最多字符出现的次数(以下简称 m a x n maxn maxn)。
利用"打擂台"的方式,挨个比较,最后统计出 m a x n maxn maxn 的值。
2.3 模拟操作
以 good 11
这组输入为例,全过程:
g o o d − > g o o d o o − > g o o d o o o o o o − > g o o d o o o o o o o o o o o o o o ( L > 11 , f i n i s h ) \;\;\;good\;->goodoo\;->goodoooooo\;->goodoooooooooooooo(L>11,finish) good−>goodoo−>goodoooooo−>goodoooooooooooooo(L>11,finish)
m a x n = 2 m a x n = 4 m a x n = 8 maxn=2\;maxn=4\;\;\;\;\;maxn=8 maxn=2maxn=4maxn=8
可以看出,每次操作后, m a x n = m a x n × 2 , ∣ S ∣ + = m a x n maxn=maxn\times 2,|S|+=maxn maxn=maxn×2,∣S∣+=maxn。
即:当 ∣ S ∣ ≥ L |S|\ge L ∣S∣≥L 时,操作结束。
3 code
#include <cstring>
#include <iostream>
#include <map>
using namespace std;
typedef unsigned long long ULL;//把unsigned long long替换成ULL节省时间
map <char,ULL> ds;
int main(){
string s;
ULL L;
cin>>s>>L;
if(s.size()>=L){//特判1.1的情况
cout<<0;
return 0;
}
for(ULL i=0;i<s.size();i++){
ds[s[i]]++;
}
ULL maxn=0;
for(ULL i=0;i<s.size();i++){
if(i==0) maxn=ds[s[i]];
else if(maxn<ds[s[i]]) maxn=ds[s[i]];
}
ULL cs=0;
L-=s.size();
while(1){
if(L<=maxn) break;
if(L>maxn) L-=maxn;
maxn*=2;
cs++;
}
cout<<cs+1;//注意按照上述方法模拟,次数是要+1再输出的
return 0;
}
4 最后的一些话
待到春暖花开时,谔谔依旧!