CF804B 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 10^{9}+7109+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 11 to 10^{6}106 .
输出格式
Print the minimum number of steps modulo 10^{9}+7109+7 .
题意翻译
题面:
你有一串字符串,仅由a,b组成,一次操作为"ab"->"bba",求使原串中没有a在b前面的操作次数. 输入格式:
仅一行: 一串长为l的字符串(只由a,b组成). 输出格式:
一个整数,即操作次数(%1e9+7). 数据范围:
l:[1,1e6] 注意:
None. 翻译贡献者:尘染梦
输入输出样例
输入 #1复制
输出 #1复制
输入 #2复制
输出 #2复制
说明/提示
The first example: "ab" →→ "bba".
The second example: "aab" →→ "abba" →→ "bbaba" →→ "bbbbaa".
题解:
这道题的暴力非常麻烦。所以我个人认为这道题要么是满分,要么是0分。
我不讲0分思路
因为这题不能用模拟,所以我们一定要从找规律和数学推导的地方入手去想。
我们随便来几个ab串。通过对这些串的分析,我们发现:我们在转换的时候,把a一点一点往后移动,一定是最优的。而且我们在完成一个ab的转换之后,对之后的结果是没有影响的(就是我们继续向下转化不会因为这次的转化而出现错误)。
那么,我们从头开始转,一定会在某一步出现这样的情况:
由一串a后面跟一串b。
类似:
aaaaa..............bbbbbbbb.
然后我们只需要考虑把这些A搞到后面去。这个时候应该从后往前推导,多用手模拟几次会发现,每次转换只将一个A依次右移,所以,我们要把所有A搞到后面去,应该会有:2的a的次数次幂减一次。
通过以上的思路打码是比较困难的。但是因为这些步骤都是不互相影响的。所以我们完全可以推出下面的共同思路:
碰到一个A,就把中间变量乘2(记得不断取模),碰到一个B,就统计一遍答案,是整个中间变量减一。
代码如下,非常巧妙:
#include<cstdio>
#include<cstring>
using namespace std;
const int maxl=1e6+1;
const int mod=1e9+7;
char s[maxl];
int ans,temp=1;
int main()
{
// freopen("seq.in","r",stdin);
// freopen("seq.out","w",stdout);
scanf("%s",s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++)
{
if(s[i]=='a')
temp=(temp<<1)%mod;
else
ans=(ans+temp-1)%mod;
}
printf("%d",ans);
return 0;
}