CF - 805D. Minimum number of steps - 思维+快速幂

1.题目描述:

D. Minimum number of steps
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

The first line contains the initial string consisting of letters 'a' and 'b' only with length from 1 to 106.

Output

Print the minimum number of steps modulo 109 + 7.

Examples
input
ab
output
1
input
aab
output
3
Note

The first example: "ab →  "bba".

The second example: "aab →  "abba →  "bbaba →  "bbbbaa".


2.题意概述:

给你一字符串,每次操作你可以把"ab"串变成“bba”,问你最少要操作多少次使得这串字符串不出现“ab”串?

3.解题思路:

容易想到的是,对于每个‘b’前面一定不能有‘a’,那么就相当于最后的字符串一定是"b...(n个b)ba...(n个a)a"的形式,可以看做把所有位于b左边的a要移到b的右边。

接下来就是统计移动次数。对于每个b,考虑它从b位置开始向左数的第i个a,例如第1个a要移到这个b右边则会多贡献一个b,那么第二个a就要移动两次,同理第二个a每移动一次都贡献一个新的b......容易发现第i个a需要移动2^(i - 1)次才能到达没有b的右侧,那么所有a移动到这个b后面就是2^0 + 2^1 + ... + 2^(i - 1),就是一个等比数列求和。

我们这样就只需要记录每个b左边的‘a’的个数,统计求和即可。注意的是求幂运算为了防止爆int可以用快速幂取模。

4.AC代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 1000100
#define lson root << 1
#define rson root << 1 | 1
#define lent (t[root].r - t[root].l + 1)
#define lenl (t[lson].r - t[lson].l + 1)
#define lenr (t[rson].r - t[rson].l + 1)
#define N 1111
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
char ch[maxn];
ll quickmod(ll a, ll b, ll m)
{
	ll ans = 1;
	while (b)//用一个循环从右到左便利b的所有二进制位
	{
		if (b & 1)//判断此时b[i]的二进制位是否为1
		{
			ans = (ans*a) % m;//乘到结果上,这里a是a^(2^i)%m
			b--;//把该为变0
		}
		b /= 2;
		a = a*a%m;
	}
	return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	long _begin_time = clock();
#endif
	while (~scanf("%s", ch))
	{
		int len = strlen(ch);
		ll ans = 0, cur = 0;
		for (int i = 0; i < len; i++)
		{
			if (ch[i] == 'a')
				cur++;
			else
				ans = (ans + quickmod(2, cur, mod) - 1) % mod;
		}
		printf("%lld\n", ans);
	}
#ifndef ONLINE_JUDGE
	long _end_time = clock();
	printf("time = %ld ms.", _end_time - _begin_time);
#endif
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值