codeforces 1245C Constanze's Machine

题目描述

Constanze is the smartest girl in her village but she has bad eyesight.

One day, she was able to invent an incredible machine! When you pronounce letters, the machine will inscribe them onto a piece of paper. For example, if you pronounce ‘c’, ‘o’, ‘d’, and ‘e’ in that order, then the machine will inscribe “code” onto the paper. Thanks to this machine, she can finally write messages without using her glasses.

However, her dumb friend Akko decided to play a prank on her. Akko tinkered with the machine so that if you pronounce ‘w’, it will inscribe “uu” instead of “w”, and if you pronounce ‘m’, it will inscribe “nn” instead of “m”! Since Constanze had bad eyesight, she was not able to realize what Akko did.

The rest of the letters behave the same as before: if you pronounce any letter besides ‘w’ and ‘m’, the machine will just inscribe it onto a piece of paper.

The next day, I received a letter in my mailbox. I can’t understand it so I think it’s either just some gibberish from Akko, or Constanze made it using her machine. But since I know what Akko did, I can just list down all possible strings that Constanze’s machine would have turned into the message I got and see if anything makes sense.

But I need to know how much paper I will need, and that’s why I’m asking you for help. Tell me the number of strings that Constanze’s machine would’ve turned into the message I got.

But since this number can be quite large, tell me instead its remainder when divided by 109+7.

If there are no strings that Constanze’s machine would’ve turned into the message I got, then print 0.

Input

Input consists of a single line containing a string s (1≤|s|≤105) — the received message. s contains only lowercase Latin letters.

Output

Print a single integer — the number of strings that Constanze’s machine would’ve turned into the message s, modulo 109+7.

Examples
input1

ouuokarinn

output1

4

input2

banana

output2

1

input3

nnn

output3

3

input4

amanda

output4

0

Note

For the first example, the candidate strings are the following: “ouuokarinn”, “ouuokarim”, “owokarim”, and “owokarinn”.

For the second example, there is only one: “banana”.

For the third example, the candidate strings are the following: “nm”, “mn” and “nnn”.

For the last example, there are no candidate strings that the machine can turn into “amanda”, since the machine won’t inscribe ‘m’.

题意:

Constanze很聪明,但是视力不好。她发明了一种机器,可以在她读单词的时候将单词记录下来。Akko搞了个恶作剧,该机器会将所有的‘m’ 变为‘nn’,将’w’, 变成‘uu’.一天,我收到了一封信(一个字符串)来自Constanze,但是我看不懂,问这个字符串原来的形式有几种可能。
如果字符串出现‘m’ 和‘w’, 则输出‘0’;

题解:

我们可以发现(以‘m’, ‘nn’ 为例,另一个同理)
当有2个连续的 ‘n’
共有两种情况:‘nn’, ‘m’
当有3个连续的 ‘n’
共有三种情况: ‘nnn’, ‘nm’, ‘mn’
当有4个连续的 ‘n’
共有五种情况: ‘nnnn’, ‘nnm’, ;nmn’, ‘mnn’, ‘mm’

再考虑 w个连续的‘n’, 记为f(w)
分两种情况
(1) 前w - 2 个连续‘n’ 的种数,再加个‘m’,f(w - 2);
(2) 前w - 1 个连续‘n’ 的种数,再加个‘n’, f(w - 1);

故 f(w) = f(w - 1) + f(w - 2)
这不就是Fibonacci数列吗

最后,我们就可以将所有含两个或两个以上的‘n’, 或‘u’的种数相乘 (利用乘法原理)

代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm> 
using namespace std;
const int N = 100005;
const int mod = 1e9 + 7;
long long fib[N];
string a;
long long mul(long long a, int b){ //快速乘,用于取模
	a %= mod;
	long long ans = 0;
	while(b){
		if(b % 2) ans = (ans + a) % mod;
		b >>= 1;
		a = a + a;
		if(a >= mod) a -= mod; 
	}
	return ans;
}
int main(){
	int i;
	fib[0] = 1;
	fib[1] = 1;
	for(i = 2; i <= N - 4; i++){ //预处理Fibonacci数列
		fib[i] = fib[i - 1] + fib[i - 2];
		if(fib[i] >= mod){
			fib[i] -= mod;
		} 
	}
	cin >> a;
	int len = a.size();
	int cnt1 = 0, cnt2 = 0;
	long long ans = 1;
	for(i = 0; i < len; i++){ //检验是否合法
		if(a[i] == 'm'){
			printf("0\n");
			return 0;
		}
		if(a[i] == 'w'){
			printf("0\n");
			return 0;
		}
	}
	for(i = 0; i < len; i++){
		if(a[i] != 'n' && cnt1 > 0){
			ans = mul(ans, fib[cnt1]);
			cnt1 = 0;
		}
		if(a[i] != 'u' && cnt2 > 0){
			ans = mul(ans, fib[cnt2]);
			cnt2 = 0;
		}
		if(a[i] == 'n'){
			cnt1++;
		}
		if(a[i] == 'u'){
			cnt2++;
		}
	}
	if(cnt1 > 0){
		ans = mul(ans, fib[cnt1]);
	}
	if(cnt2 > 0){
		ans = mul(ans, fib[cnt2]);
	}
	cout << ans << "\n";
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces 1806C题目链接:https://codeforces.com/problemset/problem/1806/C 题目描述: 给定一个长度为 $n$ 的整数序列 $a_1,a_2,\dots,a_n$,你可以进行任意多次操作,每次操作可以选择一个区间 $[l,r]$,将区间内的所有数加上 $1$ 或者减去 $1$。你的目标是使得序列中的所有数都相等,求最小的操作次数。 解题思路: 首先考虑对于一个数来说,如何将它变成序列中的所有数。由于每次操作可以将一个区间内的数全部加上或减去 $1$,所以我们可以将该数变成序列中的中位数。中位数是序列中所有数排完序后处在中间的数,如果序列长度为偶数,则中位数是中间两个数的平均数。 接下来考虑对于整个序列来说,如何将所有数变成相等的数。我们可以先将所有数变成中位数,然后计算每个数与中位数的差值之和,这个值就是最小的操作次数。 最后考虑如何将一个数变成中位数。设序列长度为 $n$,$x$ 为中位数,则有以下两种情况: - 当 $n$ 为奇数时,$x=a_{\lfloor\frac{n+1}{2}\rfloor}$。 - 当 $n$ 为偶数时,$x=\frac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}$。 对于第一种情况,我们可以将序列中所有数先减去 $a_{\lfloor\frac{n+1}{2}\rfloor}$,然后再进行操作。 对于第二种情况,我们可以将序列中所有数先减去 $\frac{a_{\frac{n}{2}}+a_{\frac{n}{2}+1}}{2}$,然后再进行操作。注意,当 $n=2$ 时,$\frac{n}{2}=1$,需要特判。 代码实现:

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值