Problem:
Score : 600 points

Problem Statement

You are given a string S of length 2N consisting of lowercase English letters.

There are 2^{2N} ways to color each character in S red or blue. Among these ways, how many satisfy the following condition?

The string obtained by reading the characters painted red from left to right is equal to the string obtained by reading the characters painted blue from right to left.

Constraints

1 \leq N \leq 18

The length of S is 2N.

S consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the number of ways to paint the string that satisfy the condition.

Sample Input 1

4
cabaacba

Sample Output 1

4

There are four ways to paint the string, as follows:

cabaacba

cabaacba

cabaacba

cabaacba

Sample Input 2

11
mippiisssisssiipsspiim

Sample Output 2

504

Sample Input 3

4
abcdefgh

Sample Output 3

0

Sample Input 4

18
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Sample Output 4

9075135300

The answer may not be representable as a 32-bit integer.

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;
using static System.Convert;
using static System.Math;
//using Debug;
//using static System.Globalization.CultureInfo;
using System.Text;
class Program
{
    static void Main(string[] args)
    {
        Solve();
        //WriteLine(Solve());
    }
    static void Solve()
    {
        var num = Input.num;
        var str = ReadLine();
        var s1 = str.Substring(0, num);
        var s2 = str.Substring(num);
        var dic1 = new Dictionary<string, int>();
        for(var i = 0; i < (1 << num); i++)
        {
            
            var q1 = new Queue<char>();
            var q2 = new Queue<char>();
            for (var j = 0; j < num; j++)
                if ((1 & i >> j) == 1) q1.Enqueue(s1[j]);
                else q2.Enqueue(s1[j]);
            var ss = new StringBuilder();
            while (q1.Any())
                ss.Append(q1.Dequeue());
            ss.Append('_');
            while (q2.Any())
                ss.Append(q2.Dequeue());
            var s = ss.ToString();
            if (dic1.ContainsKey(s))
                dic1[s]++;
            else dic1[s] = 1;
        }
        var dic2 = new Dictionary<string, int>();
        for (var i = 0; i < (1 << num); i++)
        {

            var q1 = new Stack<char>();
            var q2 = new Stack<char>();
            for (var j = 0; j < num; j++)
                if ((1 & i >> j) == 1) q1.Push(s2[j]);
                else q2.Push(s2[j]);
            var ss = new StringBuilder();
            while (q2.Any())
                ss.Append(q2.Pop());
            ss.Append('_');
            while (q1.Any())
                ss.Append(q1.Pop());
            var s = ss.ToString();
            if (dic2.ContainsKey(s))
                dic2[s]++;
            else dic2[s] = 1;
        }
        var res = 0L;
        foreach (var p in dic1)
            if (dic2.ContainsKey(p.Key))
                res += (long)p.Value * dic2[p.Key];
        WriteLine(res);
    }
}

public class Input
{
    public static string read => ReadLine().Trim();
    public static int[] ar => read.Split(' ').Select(int.Parse).ToArray();
    public  static int num => ToInt32(read);
    public static long[] arL => read.Split(' ').Select(long.Parse).ToArray();
    public  static long numL => ToInt64(read);
    public static char[][] gred(int h) 
        => Enumerable.Repeat(0, h).Select(_ => read.ToCharArray()).ToArray();
    public static int[][] ar2D(int num)
        => Enumerable.Repeat(0, num).Select(_ => ar).ToArray();
    public static long[][] arL2D(int num)
        => Enumerable.Repeat(0, num).Select(_ => arL).ToArray();
    public static T getValue<T>(string g)
    {
        var t = typeof(T);
        if (t == typeof(int))
            return (T)(object)int.Parse(g);
        if (t == typeof(long))
            return (T)(object)long.Parse(g);
        if (t == typeof(string))
            return (T)(object)g;
        if (t == typeof(char))
            return (T)(object)char.Parse(g);
        if (t == typeof(double))
            return (T)(object)double.Parse(g);
        if (t == typeof(bool))
            return (T)(object)bool.Parse(g);
        return default(T);
    }
    public const long Inf = (long)1e18;
    public const double eps = 1e-6;
    public  const string alfa = "abcdefghijklmnopqrstuvwxyz";
    public  const int MOD = 1000000007;
}