#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;
}