D. Minimum number of steps
We have a string of letters 'a' and 'b'. We want to perform some operations on it. On each step we choose one of substrings "ab" in the string and replace it with the string "bba". If we have no "ab" as a substring, our job is done. Print the minimum number of steps we should perform to make our job done modulo 109 + 7.
The string "ab" appears as a substring if there is a letter 'b' right after the letter 'a' somewhere in the string.
The first line contains the initial string consisting of letters 'a' and 'b' only with length from 1 to 106.
Print the minimum number of steps modulo 109 + 7.
ab
1
aab
3
The first example: "ab" → "bba".
The second example: "aab" → "abba" → "bbaba" → "bbbbaa".
首先进行分析,有以下规则:
1.最左方的b和最右方的a无需进行操作,也无须在意其数量
2.每次操作时,b向前移动,a向后移动
然后对于一段连续的aaab进行分析,可以得到一个初步的规律,如下
aaab→ aabba→ abbaba→ abbbbaa→ bbabbbaa→ 4babbaa→ 6babaa→ 8b3a (字母前的数字代表其数量)
一共执行了(1+2+4)次操作,那么我们可以假定n个a移动至一个b后面进行(2^0+2^1+……+2^(n-1))次操作
对于一段连续的abbb进行分析,可以得到一个初步的规律,如下
abbb→bbabb → 4bab → 6ba(字母前的数字代表其数量)
一共执行3次操作,则一个a移动至m个b后进行m次操作
所以我们可以得出结论,将n个a移动至m个b后面进行(2^n-2)*m次操作
令交换次数的答案为ans,且ans初值为0,n初值为0
每遇到一个a,则ans+=n且n=n*2,每遇到一个b,则n++
核心代码如下
for(int i=len;i>=1;i--)
{
if(s[i]=='b')n++;
else
{
ans=(ans+n)%mod;
n=(n+n)%mod;
}
}
不过一开始的时候走进了误区,没能直接看破规律,下面写上一些片面的分析,但也能助于理解上述代码
结合规则1观察出一个重要的规律,那就是我们可以将每一次操作视为使一对ab换位
现在结合以上规律对一段连续的aabb进行分析
aabb→ abbbba → 8baa
这里发现最前面的b的数量并不重要,可以等价于aabb→ (+1)abbbba →(+3) bbaa =4次
然后中间的b也可以进行简化,只需记录b的数量
等价于aabb→ (+1)abba → (+1 +2)bbaa =4次
因此每次遇到ab时,向前查询a的数量直到遇到b或边界
然后将最靠前的a替换为b,ab中的b替换为a,若a出现n次,则增加2^n-1次操作,优化后只需向前查询一次,用一个数记录a的数量即可,这样做的问题在于2^n-1必定溢出,不过可以开一个数组,对其求模即可,时间复杂度因此比上述方法复杂一些,原代码如下
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define MAX 1000000000 typedef long long ll; using namespace std; int a[1000005]; void p() { for(int i=1;i<=1000005;i++) { a[i]=2*a[i-1]%(MAX+7); } } int main() { char c[1000005]; int n,i,j,t,mar,k,time,mark; ll ans,l; a[0]=1; p(); while(scanf("%s",&c)!=EOF) { n=strlen(c); ans=0,t=0,k=0; for(i=0;i<n;i++) { if(c[i]!='b') break; k++; } for(i=k;i<n;i++) { if(c[i]=='a') { t++; } else { ans+=a[t]-1; ans%=(MAX+7); } } cout<<ans<<endl; } }