Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

アフィン暗号

簡単な暗号法の一つに、アフィン暗号というものがあります。まず、アルファベット a〜z を a = 0, b = 1, c = 2,..., x = 23, y = 24, z = 25 と 0〜25 の数字に置き換えます。そして、以下の式で、原文のアルファベットを置換します。

$F(\gamma) = (\alpha \cdot \gamma + \beta)$ mod $26$

ただし、mod 26 は 26 で割った余りを表します。例えば、$\alpha = 3, \beta = 2$ のとき、アルファベットの 'a' (=0) は、$F(0) = (3 \cdot 0 + 2)$ mod $26 = 2$ で 'c' に、アルファベットの 'n' (=13) は $F(13) = (3 \cdot 13 + 2)$ mod $26 = 15$ で 'p' に置換されます。
このとき、$\gamma$ に対する $F(\gamma)$ が必ず 1 対 1 で対応付けられるように、$\alpha$ と $\beta$ は慎重に選ばれているものとします（$\alpha$ と 26 が互いに素であることが条件）。$\alpha = 4, \beta = 7$ のときのように、$F('a') = 7, F('n') = 7$ と、'a' も 'n' も同じ 'h' に置換されるようなことはありません。また、アルファベット以外の文字は置換されません。

暗号化された文字列を元の文章に復号したものを出力するプログラムを作成してください。元の文章には、キーワードとして

that
this

のいずれかが必ず含まれているものとします。

Input

複数のデータセットが与えられます。１行目にデータセット数 $n$ ($n \leq 30$) が与えられます。続いて $n$ 行のデータが与えられます。各データセットに英小文字と空白からなる 256 文字以内の暗号化された文章が１行に与えられます。

Output

各データセットに対して、復号した元の文章を１行に出力して下さい。

Sample Input

1
y eazqyp pnop pngtg ye obmpngt xmybp mr lygw

Output for the Sample Input

i submit that there is another point of view

Solution in C# (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;

namespace AOJ.Volume0
{
    public class AffineCipher
    {
        private static Dictionary<char,int> dic = new Dictionary<char,int>()
        {
            {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3}, {'e', 4},
            {'f', 5}, {'g', 6}, {'h', 7}, {'i', 8}, {'j', 9},
            {'k', 10}, {'l', 11}, {'m', 12}, {'n', 13}, {'o', 14},
            {'p', 15}, {'q', 16}, {'r', 17}, {'s', 18}, {'t', 19},
            {'u', 20}, {'v', 21}, {'w', 22}, {'x', 23}, {'y', 24}, {'z', 25}
        };

        private static int a = 0;
        private static int b = 0;

        private static void Solve(string input)
        {
            var word = input.Split(' ');
            foreach (var w in word)
            {
                if (w.Length != 4) { continue; }

                // 最初の文字を"t"(=19)と仮定
                // aの候補(1と13以外の奇数)を当てはめてチェック
                a = 1;
                while (true)
                {
                    a += 2;
                    if (a % 13 == 0) { continue; }

                    b = 0;
                    while (true)
                    {
                        // bの候補を発見したら先のチェック
                        if (Change(w[0]) == 't') { break; }
                        b++;
                    }
                    // "this"または"that"かチェック
                    string check = "";
                    for (int i = 0; i < 4; i++)
                    {
                        check += Change(w[i]);
                    }
                    // aとbが決定
                    if (check == "that" || check == "this") { return; }
                }
            }
        }

        private static char Change(char old)
        {
            int n = (a * dic[old] + b) % 26;
            return dic.First(x => x.Value == n).Key;
        }

        public static int Main()
        {
            int count = int.Parse(Console.ReadLine());
            for (int x = 0; x < count; x++)
            {
                string input = Console.ReadLine();

                // this、またはthatを見つける
                Solve(input);

                string answer = "";
                for (int i = 0; i < input.Length; i++)
                {
                    if (input[i] == ' ') { answer += ' '; }
                    else { answer += Change(input[i]); }
                }
                Console.WriteLine(answer);
            }
            return 0;
        }
    }
}