我知道了,但你出言不逊是!
这题嘛(ldotsldots) 比赛时瞎打一通,结果真过了。
下面是正题:首先,来审题。注意只是出现,并不一定是连续出现,我在比赛一开始时没仔细看,在加上样例也有误导性,就将简单问题复杂化了。每次操作后,可增加的字符数量就会翻倍。
弄清楚题目后,就会发现其实这题就是一个再简单不过的贪心。稍微进行简单的分析,也就可以知道:在读入字符串的时候,找出出现次数最多的字符,然后一直对它出言不逊进行如题所说的操作,所需的步数就是最小的了。
cin>>s>>l;
for(register int i=0;i<s.length();++i)
{
++a[s[i]-'0']; //相当于用字符作下标。
if(a[s[i]-'0']>hsy) //当此字符数量更多时,就更新答案。
{
hsy=a[s[i]-'0'];
}
}
至于操作过程,先用一个变量存储 (|S|) 与 (L) 的差,然后进入一个死循环,在循环内判断。如果所增加的字符数大于等于 此变量,就输出,然后跳出循环;否则,将此变量减去所增加的字符,然后将每次字符增加的量乘上 (2),继续循环(ldotsldots)总有一天会达到的。
l-=s.length(); //求出梦想和现实的差距。
while(1)
{
if(hsy>=l) //如果可以出言不逊了,就输出。
{
cout<<ans<<endl;
return 0;
}
l-=hsy; //否则,差距减去增加的部分。
hsy*=2; //每次增加的数量要乘以 2。
++ans;
}
这样做的好处就是可以避免在 (nleq2^{64}) 这种毒瘤数据下会爆 usigned long long 的可能,毕竟打一个高精度是很烦的。
但它的坏处就是,在 (|S|geq L) 时,就会出错,所以要进行一次特判。
if(s.length()>=l) //此时不用变化。
{
cout<<0;
return 0;
}
交上去,就能愉快地 AC 了。
泥萌最喜欢的完整 AC 代码:
#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
string s;
ull l,a[101],hsy,ans=1;
int main()
{
cin>>s>>l;
if(s.length()>=l)
{
cout<<0;
return 0;
}
for(register int i=0;i<s.length();++i)
{
++a[s[i]-'0'];
if(a[s[i]-'0']>hsy)
{
hsy=a[s[i]-'0'];
}
}
l-=s.length();
while(1)
{
if(hsy>=l)
{
cout<<ans<<endl;
return 0;
}
l-=hsy;
hsy*=2;
++ans;
}
return 0;
}
我知道,肯定有很多大佬的程序能吊打我,但是体谅一下一个小蒟蒻吧。