Problem:
Score : 1700 points

Problem Statement

You have two strings A = A_1 A_2 ... A_n and B = B_1 B_2 ... B_n of the same length consisting of 0 and 1.
The number of 1's in A and B is equal.

You've decided to transform A using the following algorithm:

Let a_1, a_2, ..., a_k be the indices of 1's in A.

Let b_1, b_2, ..., b_k be the indices of 1's in B.

Replace a and b with their random permutations, chosen independently and uniformly.

For each i from 1 to k, in order, swap A_{a_i} and A_{b_i}.

Let P be the probability that strings A and B become equal after the procedure above.

Let Z = P \times (k!)^2. Clearly, Z is an integer.

Find Z modulo 998244353.

Constraints

1 \leq |A| = |B| \leq 10,000

A and B consist of 0 and 1.

A and B contain the same number of 1's.

A and B contain at least one 1.

Partial Score

1200 points will be awarded for passing the testset satisfying 1 \leq |A| = |B| \leq 500.

Input

Input is given from Standard Input in the following format:

A
B

Output

Print the value of Z modulo 998244353.

Sample Input 1

1010
1100

Sample Output 1

3

After the first two steps, a = [1, 3] and b = [1, 2]. There are 4 possible scenarios after shuffling a and b:

a = [1, 3], b = [1, 2]. Initially, A = 1010. After swap(A_1, A_1), A = 1010. After swap(A_3, A_2), A = 1100.

a = [1, 3], b = [2, 1]. Initially, A = 1010. After swap(A_1, A_2), A = 0110. After swap(A_3, A_1), A = 1100.

a = [3, 1], b = [1, 2]. Initially, A = 1010. After swap(A_3, A_1), A = 1010. After swap(A_1, A_2), A = 0110.

a = [3, 1], b = [2, 1]. Initially, A = 1010. After swap(A_3, A_2), A = 1100. After swap(A_1, A_1), A = 1100.

Out of 4 scenarios, 3 of them result in A = B. Therefore, P = 3 / 4, and Z = 3.

Sample Input 2

01001
01001

Sample Output 2

4

No swap ever changes A, so we'll always have A = B.

Sample Input 3

101010
010101

Sample Output 3

36

Every possible sequence of three swaps puts the 1's in A into the right places.

Sample Input 4

1101011011110
0111101011101

Sample Output 4

932171449

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;
using System.Diagnostics;



class Myon
{
    public Myon() { }
    public static int Main()
    {
        new Myon().calc();
        return 0;
    }

    Scanner cin;
    

    long mod = 998244353;

    void calc()
    {
        cin = new Scanner();
        
        string A = cin.next();
        string B = cin.next();

        if (A.Length > 500) return;

        int N = A.Length;
        int ab = 0, a = 0, b = 0;

        for (int i = 0; i < N; i++)
        {
            if (A[i] == '1')
            {
                if (B[i] == '1') ab++;
                else a++;
            }
            else if (B[i] == '1') b++;
        }

        int fab = ab;

        int turn = fab + a;

        long[,] dp = new long[a + 1, fab / 2 + 2];
        dp[a, 0] = 1;

        for (int t = 0; t < turn; t++)
        {
            int nokori = turn - t;

            long[,] ndp = new long[a + 1, fab / 2 + 2];

            for (int i = 0; i <= a; i++)
            {
                for (int j = 0; j <= fab / 2 + 1; j++)
                {
                    if (dp[i, j] == 0) continue;
                    int nowA = i;
                    int nowB = j;
                    int nowAB = (nokori - nowA - nowB);
                    if (nowAB < 0) continue;

                    long baseMul = dp[i, j];

                    if (nowA > 0)
                    {
                        ndp[nowA - 1, nowB] += baseMul * nowA * nowA; //A, A
                        //ndp[nowA - 1, nowB] += baseMul * nowA * nowB; //A-B
                        ndp[nowA - 1, nowB] %= mod;
                    }


                    if (nowAB > 0)
                    {
                        ndp[nowA, nowB] += baseMul * nowAB * nowA;   //AB, A
                        ndp[nowA, nowB] += baseMul * nowAB;  //AB same
                        ndp[nowA, nowB] += baseMul * nowAB * nowB * 2;  //AB-B, B-AB

                        ndp[i, j] %= mod;

                        if (nowAB > 1)
                        {
                            ndp[nowA, nowB + 1] = baseMul * nowAB * (nowAB - 1); //AB mismatch
                            ndp[nowA, nowB + 1] %= mod;
                        }
                    }
                    if(nowB > 0)
                    {
                        ndp[nowA, nowB - 1] += baseMul * nowB * nowB; //B-B
                        ndp[nowA, nowB - 1] %= mod;
                        
                    }
                }
            }
            
            dp = ndp;
        }

        Console.WriteLine(dp[0, 0]);
    }
}


class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        if (s.Length == 0) return next();
        i = 0;
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }
    public int[] ArrayInt(int N, int add = 0)
    {
        int[] Array = new int[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextInt() + add;
        }
        return Array;
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public long[] ArrayLong(int N, long add = 0)
    {
        long[] Array = new long[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextLong() + add;
        }
        return Array;
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }


    public double[] ArrayDouble(int N, double add = 0)
    {
        double[] Array = new double[N];
        for (int i = 0; i < N; i++)
        {
            Array[i] = nextDouble() + add;
        }
        return Array;
    }
}