#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll N = 2e5 + 5, M = 2000120420010122;
ll f[N];
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
// 多组测试用例循环处理
while (true) {
string s;
cin >> s;
if(s.empty())break;
// 算法核心:分阶段计数法,跟踪Cwbc子序列的各前缀阶段数量,线性遍历无嵌套,时间复杂度O(n)
// 阶段1:统计已出现的'C/c'的数量(子序列第1位)
ll cnt_c=0;
// 阶段2:统计已出现的'Cw/CW/cw/cW'子序列的数量(子序列前2位)
ll cnt_cw=0;
// 阶段3:统计已出现的'Cwb/CWB/cwb/cWB'子序列的数量(子序列前3位)
ll cnt_cwb=0;
// 重置答案数组f,避免多组测试用例的历史数据干扰
memset(f,0,sizeof f);
// 线性遍历字符串,i为前i个字符的下标(从1开始),s[i-1]对应当前遍历的字符
for (ll i = 1; i <= s.size(); i++) {
// 步骤1:继承前i-1个字符的答案,当前字符无新贡献时,答案保持不变
f[i]=f[i-1];
// 情况1:遇到'C/c'(子序列第4位,也是新的第1位)
if (s[i - 1] == 'c' || s[i - 1] == 'C') {
// 核心逻辑:当前C可与所有已存在的Cwb前缀(阶段3)构成完整Cwbc子序列,更新答案
f[i]=(f[i]+cnt_cwb)%M;
// 新增一个C,阶段1的计数+1,取模防止溢出
cnt_c++;
cnt_c%=M;
}
// 情况2:遇到'W/w'(子序列第2位)
else if (s[i - 1] == 'w' || s[i - 1] == 'W') {
// 核心逻辑:每个已存在的C(阶段1)可与当前W构成Cw子序列,阶段2计数累加阶段1数量
cnt_cw=(cnt_cw+cnt_c)%M;
}
// 情况3:遇到'B/b'(子序列第3位)
else if (s[i - 1] == 'b' || s[i - 1] == 'B') {
// 核心逻辑:每个已存在的Cw(阶段2)可与当前B构成Cwb子序列,阶段3计数累加阶段2数量
cnt_cwb=(cnt_cwb+cnt_cw)%M;
}
}
// 输出整个字符串的总合法Cwbc子序列数量(f[s.size()]为前s.size()个字符的最终答案)
cout << f[s.size()] << endl;
}
return 0;
}