Problem:
Generic Poker
You have a deck of
N
×
M
cards. Each card in the deck has a rank. The range of ranks is 1 through
M
, and the deck includes
N
cards of each rank.
We denote a card with rank
m
by
m
here.
You can draw a hand of
L
cards at random from the deck.
If the hand matches the given pattern,
some bonus will be rewarded.
A pattern is described as follows.
hand_pattern = card_pattern
1
' ' card_pattern
2
' ' ... ' ' card_pattern
L
card_pattern = '*' | var_plus
var_plus = variable | var_plus '+'
variable = 'a' | 'b' | 'c'
hand_pattern
A hand matches the hand_pattern if each card_pattern in the hand_pattern matches with a distinct card in the hand.
card_pattern
If the card_pattern is an asterisk ('*'), it matches any card. 
Characters 'a', 'b', and 'c' denote variables and all the occurrences of the same variable match cards of the same rank.
A card_pattern with a variable followed by plus ('+')
characters matches a card whose rank is the sum of the rank corresponding to the variable
and the number of plus characters.

You can assume that, when a hand_pattern includes a card_pattern with
a variable followed by some number of plus characters, it also
includes card_patterns with that variable and all smaller numbers (including zero) of plus characters.
For example, if 'a+++' appears in a hand_pattern, card_patterns 'a',
'a+', and 'a++' also appear in the hand_pattern.
There is no restriction on which ranks different variables mean.
For example, 'a' and 'b' may or may not match cards of the same rank.
We show some example hand_patterns. The pattern
a * b a b
matches the hand:
3 3 10 10 9
with 'a's and 'b's meaning 3 and 10 (or 10 and 3),
respectively. This pattern also matches the following hand.
3 3 3 3 9
In this case, both 'a's and 'b's mean 3.  The pattern
a a+ a++ a+++ a++++
matches the following hand.
4 5 6 7 8
In this case, 'a' should mean 4.
Your mission is to write a program that computes the probability that
a hand randomly drawn from the deck matches the given hand_pattern.
Input
The input is a sequence of datasets. Each dataset is formatted as follows.
N
M
L
card_pattern
1
card_pattern
2
...
card_pattern
L
The first line consists of three positive integers
N
,
M
, and
L
.
N
indicates the number of cards in each rank,
M
indicates the number of ranks, and
L
indicates the number of cards in a hand.
N
,
M
, and
L
are constrained as follows.
1 ≤
N
≤ 7
1 ≤
M
≤ 60
1 ≤
L
≤ 7
L
≤
N
×
M
The second line describes a hand_pattern.
The end of the input is indicated by a line containing three zeros 
separated by a single space.
Output
For each dataset, output a line containing a decimal fraction which means the probability of a hand matching the hand_pattern.
The output should not contain an error greater than 10
−8
.
No other characters should be contained in the output.
Sample Input
1 1 1
a
3 3 4
a+ * a *
2 2 3
a a b
2 2 3
* * *
2 2 3
* b b
2 2 2
a a
2 3 3
a a+ a++
2 6 6
a a+ a++ b b+ b++
4 13 5
a a * * *
4 13 5
a a b b *
4 13 5
a a a * *
4 13 5
a a+ a+
...(truncated)

Submitted solutions:

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 2 "cp-library/src/number/binom_table.hpp"

template < class T >
std::vector< std::vector< T > > binom_table(int N) {
    std::vector table(N + 1, std::vector(N + 1, T(0)));
    table[0][0] = 1;
    for(int i : rep(1, N + 1)) {
        table[i][0] = 1;
        for(int j : rep(1, N + 1))
            table[i][j] = table[i - 1][j - 1] + table[i - 1][j];
    }
    return table;
}
#line 4 "A.cpp"

auto comb = binom_table<i64>(500);

f64 solve(int N, int M, int L) {
    vector<string> pattern = in(L);
    sort(pattern);

    vector<vector<int>> freqency;
    {
        map<char, vector<int>> mp;
        for(string s : pattern) {
            if(s == "*") {
                freqency.push_back({1});
            } else {
                int c = s.size() - 1;
                while(mp[s[0]].size() <= c) mp[s[0]].push_back(0);
                mp[s[0]][c] += 1;
            }
        }
        for(auto [key, vec] : mp) freqency.push_back(vec);
    }

    const int fsz = freqency.size();
    sort(freqency);
    set<vector<vector<int>>> st;
    do {
        auto dfs = [&](auto self, vector<vector<int>> now, int i) -> void {
            if(i == fsz) {
                st.insert(now);
                return;
            }

            now.push_back(freqency[i]);
            self(self, now, i + 1);
            now.pop_back();

            const int p = now.back().size();
            const int q = freqency[i].size();
            for(int j = 0; j <= p; j++) {
                vector<int> nxt(max(p, j + q), 0);
                for(int k = 0; k < p; k++) nxt[k] += now.back()[k];
                for(int k = 0; k < q; k++) nxt[j + k] += freqency[i][k];
                swap(nxt, now.back());
                self(self, now, i + 1);
                swap(nxt, now.back());
            }
            
        };
        dfs(dfs, {freqency[0]}, 1);
    } while(next_permutation(freqency.begin(), freqency.end()));

    i64 ans = 0;
    for(vector<vector<int>> a : st) {
        const int n = a.size();
        i64 f = 1;
        int s = n - 1;
        for(int i : rep(n)) {
            for(int c : a[i]) f *= comb[N][c];
            s += a[i].size();
        }
        if(0 <= M - s) ans += f * comb[M - s + n][n];
    }
    return ans / f64(comb[N * M][L]);
}

int main() {
    while(true) {
        int N = in(), M = in(), L = in();
        if(make_tuple(N, M, L) == make_tuple(0, 0, 0)) return 0;
        printer::precision(20);
        print(solve(N, M, L));
    }
}
accuracy: 1
time_ms: 20
memory_kb: 5680
final_rank: 16

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 2 "cp-library/src/number/binom_table.hpp"

template < class T >
std::vector< std::vector< T > > binom_table(int N) {
    std::vector table(N + 1, std::vector(N + 1, T(0)));
    table[0][0] = 1;
    for(int i : rep(1, N + 1)) {
        table[i][0] = 1;
        for(int j : rep(1, N + 1))
            table[i][j] = table[i - 1][j - 1] + table[i - 1][j];
    }
    return table;
}
#line 4 "A.cpp"

auto comb = binom_table<i64>(500);

f64 solve(int N, int M, int L) {
    vector<string> pattern = in(L);
    sort(pattern);

    vector<vector<int>> freqency;
    {
        map<char, vector<int>> mp;
        for(string s : pattern) {
            if(s == "*") {
                freqency.push_back({1});
            } else {
                int c = s.size() - 1;
                while(mp[s[0]].size() <= c) mp[s[0]].push_back(0);
                mp[s[0]][c] += 1;
            }
        }
        for(auto [key, vec] : mp) freqency.push_back(vec);
    }

    const int fsz = freqency.size();
    sort(freqency);
    set<vector<vector<int>>> st;
    do {
        auto dfs = [&](auto self, vector<vector<int>> now, int i) -> void {
            if(i == fsz) {
                st.insert(now);
                return;
            }

            now.push_back(freqency[i]);
            self(self, now, i + 1);
            now.pop_back();

            const int p = now.back().size();
            const int q = freqency[i].size();
            for(int j = 0; j <= p; j++) {
                vector<int> nxt(max(p, j + q), 0);
                for(int k = 0; k < p; k++) nxt[k] += now.back()[k];
                for(int k = 0; k < q; k++) nxt[j + k] += freqency[i][k];
                swap(nxt, now.back());
                self(self, now, i + 1);
                swap(nxt, now.back());
            }
            
        };
        dfs(dfs, {freqency[0]}, 1);
    } while(next_permutation(freqency.begin(), freqency.end()));

    i64 ans = 0;
    for(vector<vector<int>> a : st) {
        const int n = a.size();
        i64 f = 1;
        int s = n - 1, t = n - 1;
        for(int i : rep(n)) {
            for(int c : a[i]) f *= comb[N][c];
            s += a[i].size();
        }
        if(0 <= M - s) ans += f * comb[M - s + t + 1][t + 1];
    }
    return ans / f64(comb[N * M][L]);
}

int main() {
    while(true) {
        int N = in(), M = in(), L = in();
        if(make_tuple(N, M, L) == make_tuple(0, 0, 0)) return 0;
        printer::precision(20);
        print(solve(N, M, L));
    }
}
accuracy: 1
time_ms: 20
memory_kb: 5612
final_rank: 15

code_snippet: #include <bits/stdc++.h>

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}

template<typename T> struct comb {
	std::vector<std::vector<T> > ncr;
	std::vector<T> fact;
	comb (int n) : ncr(n + 1), fact(n + 1, 1) {
		for (int i = 0; i <= n; i++) {
			ncr[i].resize(i + 1, 1);
			for (int j = 1; j < i; j++) ncr[i][j] = ncr[i - 1][j] + ncr[i - 1][j - 1];
		}
		for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i;
	}
};

bool match(std::vector<int> b, std::vector<std::vector<int> > lens) {
	if (!lens.size()) return true;
	
	for (size_t i = 0; i < lens.size(); i++) {
		auto len = lens[i];
		auto new_lens = lens;
		new_lens.erase(new_lens.begin() + i);
		
		for (int j = 0; j + (int) len.size() <= (int) b.size(); j++) {
			auto new_b = b;
			bool ok = true;
			for (int k = 0; k < (int) len.size(); k++) {
				if (new_b[j + k] < len[k]) {
					ok = false;
					break;
				}
				new_b[j + k] -= len[k];
			}
			if (ok && match(new_b, new_lens)) return true;
		}
	}
	return false;
}

bool solve() {
	int n = ri();
	int m = ri();
	int l = ri();
	if (!n && !m && !l) return false;
	std::vector<int> cnt[3];
	for (int i = 0; i < l; i++) {
		std::string s;
		std::cin >> s;
		if (s == "*") continue;
		auto &target = cnt[s[0] - 'a'];
		int cnt = (int) s.size() - 1;
		if ((int) target.size() <= cnt) target.resize(cnt + 1);
		target[cnt]++;
	}
	
	comb<uint64_t> com(n * m);
	
	std::vector<int> a(l - 1); // 0 : +0, 1 : +1, 2 : next component
	int64_t res = 0;
	while (1) {
		std::vector<std::vector<int> > unions;
		unions.push_back({ 1 });
		std::vector<int> b = { 1 };
		for (auto i : a) {
			if (i == 0) b.back()++, unions.back().back()++;
			else if (i == 1) b.push_back(1), unions.back().push_back(1);
			else b.push_back(0), b.push_back(1), unions.push_back({ 1 });
		}
		if (std::is_sorted(unions.begin(), unions.end())) {
			bool ok = match(b, {cnt[0], cnt[1], cnt[2]});
			for (auto i : b) if (i > n) ok = false;
			if ((int) b.size() > m) ok = false;
			
			if (ok) {
				/*
				for (auto i : b) std::cerr << i << " ";
				std::cerr << " : " << ok << std::endl;*/
				
				std::map<std::vector<int>, int> cnt;
				std::vector<int> cur;
				b.push_back(0);
				for (auto i : b) {
					if (i) cur.push_back(i);
					else cnt[cur]++, cur.clear();
				}
				b.pop_back();
				
				int64_t cur_res = 1;
				cur_res *= com.fact[unions.size()];
				for (auto &i : cnt) cur_res /= com.fact[i.second];
				for (auto i : b) if (i) cur_res *= com.ncr[n][i];
				cur_res *= com.ncr[unions.size() + (m - (int) b.size())][unions.size()];
				// std::cerr << "  : ! "<< cur_res << std::endl;
				
				res += cur_res;
			}
		}
		
		int head = 0;
		while (head < l - 1 && ++a[head] == 3) a[head++] = 0;
		if (head == l - 1) break;
	}
	
	printf("%.11f\n", (double) res / com.ncr[n * m][l]);
	
	return true;
}
int main() {
	while (solve());
	return 0;
}
accuracy: 1
time_ms: 610
memory_kb: 3764
final_rank: 13

code_snippet: #include <map>
#include <set>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;

int64_t comb(int x, int y) {
	if (x < y || y < 0) {
		return 0;
	}
	int64_t res = 1;
	for (int i = 1; i <= y; i++) {
		res *= x - y + i;
		res /= i;
	}
	return res;
}

int main() {
	while (true) {
		int N, M, L;
		cin >> N >> M >> L;
		if (N == 0 && M == 0 && L == 0) {
			break;
		}
		vector<vector<int> > vars;
		map<char, vector<int> > d;
		for (int i = 0; i < L; i++) {
			string str;
			cin >> str;
			if (str == "*") {
				vars.push_back(vector<int>({ 1 }));
			}
			else {
				d[str[0]].push_back(int(str.size()) - 1);
			}
		}
		for (pair<char, vector<int> > i : d) {
			vector<int> v = i.second;
			int sz = *max_element(v.begin(), v.end()) + 1;
			vector<int> subvar(sz);
			for (int j : v) {
				subvar[j] += 1;
			}
			vars.push_back(subvar);
		}
		sort(vars.begin(), vars.end());
		set<vector<int> > s;
		do {
			function<void(int, int, vector<int>)> dfs = [&](int pos, int l, vector<int> seq) {
				if (pos == int(vars.size())) {
					s.insert(seq);
					return;
				}
				int64_t res = 0;
				int nextl = (pos == 0 || vars[pos - 1] <= vars[pos] ? l : l + 1);
				for (int i = nextl; i <= int(seq.size()); i++) {
					int limit_size = i + vars[pos].size();
					vector<int> nseq = seq;
					if (int(seq.size()) < limit_size) {
						nseq.resize(limit_size);
					}
					for (int j = 0; j < int(vars[pos].size()); j++) {
						nseq[i + j] += vars[pos][j];
					}
					dfs(pos + 1, i, nseq);
				}
				if (pos >= 1) {
					vector<int> nseq_base = seq;
					nseq_base.push_back(0);
					nseq_base.insert(nseq_base.end(), vars[pos].begin(), vars[pos].end());
					dfs(pos + 1, seq.size() + 1, nseq_base);
				}
			};
			dfs(0, 0, vector<int>());
		} while (next_permutation(vars.begin(), vars.end()));
		int64_t answer = 0;
		for (vector<int> v : s) {
			int sz = v.size();
			int blanks = 0;
			for (int i = 0; i < sz; i++) {
				if (v[i] == 0) {
					blanks += 1;
				}
			}
			int64_t subres = comb((M - (sz - blanks)) + 1, blanks + 1);
			for (int i = 0; i < sz; i++) {
				subres *= comb(N, v[i]);
			}
			answer += subres;
		}
		int64_t combs = comb(N * M, L);
		cout.precision(18);
		cout << fixed << (long double)(answer) / (long double)(combs) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3636
final_rank: 8

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000009;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 10;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

vector<vector<int>> vs[8];

ld pas[100][100];
void init() {
	vs[1].push_back({ 0 });
	for (int c = 1; c < 7; c++) {
		for (auto v : vs[c]) {
			int ma = 0;
			for (int val : v)ma = max(ma, val);
			rep(i, ma + 2) {
				vector<int> nv = v;
				nv.push_back(i);
				sort(all(nv));
				vs[c + 1].push_back(nv);
			}
		}
		sort(all(vs[c + 1]));
		vs[c + 1].erase(unique(all(vs[c + 1])), vs[c + 1].end());
	}
	rep(i, 100)rep(j, 100) {
		if (i == 0 || j == 0)pas[i][j] = 1;
		else pas[i][j] = pas[i - 1][j] + pas[i][j - 1];
	}
}

int n, m, l;
void solve() {
	vector<string> vc(l); rep(i, l)cin >> vc[i];
	auto isok = [&](vector<int> v) {
		vector<int> vals = v;
		sort(all(vals));
		vals.erase(unique(all(vals)), vals.end());
		multiset<int> st; for (int val : v)st.insert(val);
		rep(a, vals.size())rep(b, vals.size())rep(c, vals.size()) {
			array<int, 3> ar = { vals[a],vals[b],vals[c] };
			multiset<int> cop = st;
			bool valid = true;
			rep(i, l) {
				if (vc[i][0] == '*')continue;
				int val = ar[vc[i][0] - 'a'];
				val += vc[i].size() - 1;
				if (cop.find(val) == cop.end())valid = false;
				else cop.erase(cop.find(val));
			}
			if (valid)return true;
		}
		return false;
	};
	vector<vector<int>> vv;
	for (int c = 1; c <= l; c++) {
		for (auto v : vs[c])vv.push_back(v);
	}
	vector<vector<vector<int>>> vp(l + 1);
	vp[0].push_back({});
	rep(i, vv.size()) {
		rep(j, l+1) {
			int nj = j + vv[i].size();
			if (nj <= l) {
				for (auto v : vp[j]) {
					vector<int> nv = v; nv.push_back(i);
					vp[nj].push_back(nv);
				}
			}
		}
	}
	ld al = 1;
	rep(i, l)al *= n * m - i;
	rep1(i, l)al /= i;
	ld ans = 0;
	for (auto v : vp[l]) {
		vector<int> vals;
		int cur = 0;
		for (int loc : v) {
			rep(i, vv[loc].size()) {
				vals.push_back(cur + vv[loc][i]);
			}
			cur += vv[loc].back() + 2;
		}
		//rep(i, vals.size()) {
		//	cout << vals[i] << " ";
		//}cout << "\n";
		if (isok(vals)) {
			ld num = 1;
			rep(i, vals.size()) {
				int cnt = 1;
				while (i + 1 < vals.size() && vals[i] == vals[i + 1]) {
					i++; cnt++;
				}
				//n C cnt
				if (n < cnt)num = 0;
				else {
					rep(i, cnt) {
						num *= n-i;
						num /= i + 1;
					}
				}
			}
			rep(i, v.size())num *= i + 1;
			rep(i, v.size()) {
				int cnt = 1;
				while (i + 1 < v.size() && v[i] == v[i + 1]) {
					i++; cnt++;
				}
				rep(j, cnt)num /= j + 1;
			}
			int r = m - (cur - 1);
			if (r < 0)continue;
			int t = v.size();
			num *= pas[r][t];
			
			//cout << num << "\n";
			ans += num;
		}
	}
	ans /= al;
	cout << ans << "\n";
}



signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//init_f();
	init();
	//int t; cin >> t; rep(i, t)
	while(cin>>n>>m>>l,n)
	solve();
	return 0;
}
accuracy: 1
time_ms: 760
memory_kb: 3760
final_rank: 14

code_snippet: //Let's join Kaede Takagaki Fan Club !!
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
#define all(x) x.begin(),x.end()
template<class T>
void dmp(T a){
	rep(i,a.size()) cout << a[i] << " ";
	cout << endl;
}
template<class T>
bool chmax(T&a, T b){
	if(a < b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
bool chmin(T&a, T b){
	if(a > b){
		a = b;
		return 1;
	}
	return 0;
}
template<class T>
void g(T &a){
	cin >> a;
}
template<class T>
void o(const T &a,bool space=false){
	cout << a << (space?' ':'\n');
}
//ios::sync_with_stdio(false);
const ll mod = 1000000007;//998244353
template<class T>
void add(T&a,T b){
	a+=b;
	if(a >= mod) a-=mod;
}
typedef long double ld;
set<pair<vector<vector<int>>, long double>>S[8];

void dfs(vector<int>vec, int num){
	if(vec.size() == num-1){
		vector<vector<int>>ret;
		vector<int>zan({1});
		for(int i=0;i<vec.size();i++){
			if(vec[i] == 0) zan.back()++;
			else if(vec[i] == 1) zan.pb(1);
			else {
				ret.pb(zan);
				zan = vector<int>({1});
			}
		}
		ret.pb(zan); SORT(ret);
		long double way = 1.0L;
		repn(i, ret.size()) way = way * (ld)i;
		vector<int>pre;
		int cnt = 1;
		rep(i, ret.size()){
			if(pre != ret[i]){
				repn(i, cnt) way /= (ld)i;
				pre = ret[i]; cnt = 1;
			}
			else cnt++;
		}
		repn(i, cnt) way /= (ld)i;
		S[num].insert(mp(ret, way)); return;
	}
	for(int i=-1;i<=1;i++){
		vec.pb(i);
		dfs(vec, num);
		vec.pop_back();
	}
}
int n, m, a;
bool check(vector<vector<int>>vec, vector<vector<int>>cnt, int nxt){
	if(nxt == 3){
		rep(i, vec.size()) rep(j, vec[i].size()) if(vec[i][j] < 0) return 0;
		return 1;
	}
	rep(i, vec.size()){
		rep(j, vec[i].size()){
			bool bad = 0;
			rep(k, cnt[nxt].size()){
				if(cnt[nxt][k] > 0 && j+k >= vec[i].size()) {bad = 1; break;}
			}
			if(bad) continue;
			rep(k, cnt[nxt].size()){
				if(j+k >= vec[i].size()) break;
				vec[i][j+k] -= cnt[nxt][k];
				if(vec[i][j+k] < 0) bad = 1;
			}
			if(!bad && check(vec, cnt, nxt+1)) return true;
			rep(k, cnt[nxt].size()){
				if(j+k >= vec[i].size()) break;
				vec[i][j+k] += cnt[nxt][k];
			}
		}
	}
	return false;
}
ld C(int a, int b){
	ld ret = 1.0L;
	for(int i=0;i<b;i++){
		ret = ret * (ld)(a-i) / (ld)(i+1);
	}
	return ret;
}
void solve(){
	vector<vector<int>>cnt;
	rep(i, 3){
		cnt.pb(vector<int>(10, 0));
	}
	rep(i, a){
		string s; cin >> s;
		if(s[0] == '*') continue;
		else{
			cnt[s[0]-'a'][s.size()-1] ++;
		}
	}
	ld ans = 0., all = 0.;
	for(const auto at:S[a]){
		bool ok = check(at.fi, cnt, 0);
		ld coef = (ld)(at.sc);
		int b = at.fi.size(), c = b-1, bad = 0;
		rep(i, b){
			c += (at.fi)[i].size();
			rep(j, (at.fi)[i].size()){
				if( (at.fi)[i][j] > n) bad = 1;
				coef = coef * C(n, (at.fi)[i][j]);
			}
		}
		if(bad) continue;
		if(m-c >= 0) all += C(m-c+b, b) * coef;
		if(ok && m-c >= 0) ans += C(m-c+b, b) * coef;
	}
	printf("%.10Lf\n", ans / all);
}
int main(){
	for(int i=1;i<=7;i++){
		dfs(vector<int>(), i);
	}
	while(1){
		cin >> n >> m >> a;
		if(n == 0 && m == 0 && a == 0) return 0;
		solve();
	}
}
accuracy: 1
time_ms: 30
memory_kb: 3404
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

using int64 = long long;
const int mod = 1e9 + 7;
// const int mod = 998244353;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 > &p) {
  os << p.first << " " << p.second;
  return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
  is >> p.first >> p.second;
  return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
  for(T &in : v) is >> in;
  return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e : t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

template< typename T >
vector< vector< T > > binomial_table(int N) {
  vector< vector< T > > mat(N + 1, vector< T >(N + 1));
  for(int i = 0; i <= N; i++) {
    for(int j = 0; j <= i; j++) {
      if(j == 0 || j == i) mat[i][j] = 1;
      else mat[i][j] = mat[i - 1][j - 1] + mat[i - 1][j];
    }
  }
  return mat;
}

int main() {
  int N, M, L;

  auto C = binomial_table< double >(150);

  auto dp = make_v< double >(61, 8, 8);
  auto memo = make_v< int >(61, 8, 8);
  auto rec = MFP([&](auto rec, int M, int N, int L) -> double {
    if(M == 0) return L == 0 ? 1.0 : 0.0;
    if(memo[M][N][L]) return dp[M][N][L];
    memo[M][N][L] = true;
    double ret = 0.0;
    for(int i = 0; i <= N && i <= L; i++) {
      ret += rec(M - 1, N, L - i) * C[N][i];
    }
    return dp[M][N][L] = ret;
  });

  while(cin >> N >> M >> L, N) {
    auto rank = make_v< int >(3, L);
    int any = 0;
    for(int i = 0; i < L; i++) {
      string s;
      cin >> s;
      if(s != "*") ++rank[s[0] - 'a'][(int) s.size() - 1];
      else any++;
    }
    for(int i = 0; i < 3; i++) {
      while(!rank[i].empty() && rank[i].back() == 0) {
        rank[i].pop_back();
      }
    }
    vector< int > op;

    auto is_match = [&]() -> bool {
      for(int i = 0; i + rank[0].size() <= op.size(); i++) {
        for(int j = 0; j + rank[1].size() <= op.size(); j++) {
          for(int k = 0; k + rank[2].size() <= op.size(); k++) {
            for(int l = 0; l < rank[0].size(); l++) {
              op[i + l] -= rank[0][l];
            }
            for(int l = 0; l < rank[1].size(); l++) {
              op[j + l] -= rank[1][l];
            }
            for(int l = 0; l < rank[2].size(); l++) {
              op[k + l] -= rank[2][l];
            }
            bool f = true;
            for(int l = 0; l < op.size(); l++) {
              f &= op[l] >= 0;
            }
            for(int l = 0; l < rank[0].size(); l++) {
              op[i + l] += rank[0][l];
            }
            for(int l = 0; l < rank[1].size(); l++) {
              op[j + l] += rank[1][l];
            }
            for(int l = 0; l < rank[2].size(); l++) {
              op[k + l] += rank[2][l];
            }
            if(f) return true;
          }
        }
      }
      return false;
    };
    double ue = 0;
    MFP([&](auto generate, int sum, int space) -> void {
      if(sum == L) {
        if(is_match()) {
          int f_sz = 0;
          while(f_sz < op.size() && op[f_sz] > 0) ++f_sz;
          int more = 0;
          for(int i = f_sz + 1; i < op.size(); i++) {
            if(op[i - 1] >= 1 && op[i] >= 1) ++more;
          }
          double mul = 0;
          for(int first = 0; first + f_sz <= M; first++) {
            int rest = M - (first + f_sz) - more;
            if(rest - space >= 0) {
              mul += C[rest - space][space];
            }
          }
          double vv = 1;
          for(int i = 0; i < op.size(); i++) {
            vv *= C[N][op[i]];
          }
          ue += vv * mul;
        }
        return;
      }
      op.emplace_back(0);
      if(op.size() >= 2 && op[op.size() - 2] > 0) {
        generate(sum, space + 1);
      }
      for(int i = 1; i <= N && sum + i <= L; i++) {
        op.back() = i;
        generate(sum + i, space);
      }
      op.pop_back();
    })(0, 0);
    cout << ue / rec(M, N, L) << endl;
  }
}
accuracy: 1
time_ms: 380
memory_kb: 3440
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Info{

	char ch;
	int maximum,count_table[7];
};

int table[7],work[7];
int N,M,L;
int check_index;
ll dp[8][61];
double nCm[421][8];
char pattern[7][10];
char check_table[5040][7];
vector<vector<Info>> SECTION;
Info info[7],calc_info[7],work_info[7],section[7];


//連続した数字の塊【区間】を0～M-1に当てはめる【最大L個】
ll dfs(int section_index,int num_section,int num_index){

	if(num_index == M){

		if(section_index < num_section){ //当てはめをしていない区間あり

			return 0;
		}else{

			return 1;
		}
	}

	if(dp[section_index][num_index] != -1){

		return dp[section_index][num_index];
	}

	ll ret = 0;

	//割り当てない
	ret += dfs(section_index,num_section,num_index+1);

	//割り当てる
	if(section_index < num_section){

		int tail = num_index+section[section_index].maximum;
		if(tail <= M-1){

			//★重複計上を防ぐため、区間と区間の間には少なくとも1つの空白を設ける★
			ret += dfs(section_index+1,num_section,min(M,tail+2));
		}
	}

	return dp[section_index][num_index] = ret;
}

void makeSection(int section_index,int num_info,int work_index){

	if(section_index == num_info){ //区間作成完了

		//既存区間と重複していないか調べる
		bool FLG = false;

		for(int i = 0; i < SECTION.size(); i++){
			FLG = true;
			if(SECTION[i].size() != work_index){ //区間の数が異なるならOK
				FLG = false;
				continue;
			}
			for(int k = 0; k < SECTION[i].size(); k++){
				if(SECTION[i][k].maximum != work_info[k].maximum){ //ある区間の長さが異なるならOK

					FLG = false;
					break;
				}
				for(int p = 0; p <= SECTION[i][k].maximum; p++){
					if(SECTION[i][k].count_table[p] != work_info[k].count_table[p]){ //ある数字の数が異なるならOK

						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}
			if(FLG)break;
		}

		if(FLG)return;

		vector<Info> vec;

		for(int i = 0; i < work_index; i++){

			vec.push_back(work_info[i]);
		}

		SECTION.emplace_back(vec);

		return;
	}

	//既存の区間と重なりを持つ場合
	for(int i = 0; i < work_index; i++){
		for(int merge_head = 0; merge_head <= work_info[i].maximum+1; merge_head++){

			if(merge_head+calc_info[section_index].maximum >= min(L,M))continue;

			//数字の個数がNを越えないか調べる
			bool FLG = true;
			for(int k = 0; merge_head+k <= work_info[i].maximum && k <= calc_info[section_index].maximum; k++){
				if(work_info[i].count_table[merge_head+k]+calc_info[section_index].count_table[k] > N){

					FLG = false;
					break;
				}
			}

			if(!FLG)continue;

			int pre_max = work_info[i].maximum;

			for(int k = 0; k <= calc_info[section_index].maximum; k++){
				work_info[i].count_table[merge_head+k] += calc_info[section_index].count_table[k];
				work_info[i].maximum = max(work_info[i].maximum,merge_head+k);
			}

			makeSection(section_index+1,num_info,work_index);

			//元に戻す
			for(int k = 0; k <= calc_info[section_index].maximum; k++){
				work_info[i].count_table[merge_head+k] -= calc_info[section_index].count_table[k];
			}
			work_info[i].maximum = pre_max;
		}
	}


	//新しい区間とする場合
	work_info[work_index] = calc_info[section_index];
	makeSection(section_index+1,num_info,work_index+1);
}


void func(){

	for(int i = 0; i < L; i++){

		scanf("%s",pattern[i]);
	}
	printf("\n");

	SECTION.clear();

	double num_all = nCm[N*M][L];

	/*patternに該当する場合の数を計上する*/

	//pattern情報を調べる
	int num_info = 0;
	for(int i = 0; i < 7; i++){
		for(int k = 0; k < 7; k++){
			info[i].count_table[k] = 0;
		}
	}

	for(int i = 0; i < L; i++){

		if(pattern[i][0] == '*'){ //独立させる

			info[num_info].ch = '*';
			info[num_info].maximum = 0;
			info[num_info].count_table[0] = 1;

			num_info++;

		}else{

			int index = -1;

			for(int k = 0; k < num_info; k++){

				if(info[k].ch == pattern[i][0]){

					index = k;
					break;
				}
			}

			if(index == -1){

				info[num_info].ch = pattern[i][0];
				info[num_info].maximum = 0;
				index = num_info;
				num_info++;
			}

			int num_plus = 0;

			for(int k = 1; pattern[i][k] == '+'; k++,num_plus++);

			info[index].count_table[num_plus] += 1; //a a a++ a++ a+++ 等
			info[index].maximum = max(info[index].maximum,num_plus);
		}
	}

	//patternにマッチする場合を数え上げる
	//★★★★異なる変数の間には、表すランクについての制約はない★★★★

	//区間の集合を作成する
	int perm_table[7];
	for(int i = 0; i < num_info; i++){
		perm_table[i] = i;
	}

	check_index = 0;

	do{

		for(int i = 0; i < num_info; i++){ //infoを固定すると計上漏れが発生する

			calc_info[i] = info[perm_table[i]];
		}

		bool FLG = false;

		//既に処理していないか調べる
		for(int i = 0; i < check_index; i++){
			FLG = true;
			for(int k = 0; k < num_info; k++){
				if(check_table[i][k] != calc_info[k].ch){
					FLG = false;
					break;
				}
			}
			if(FLG)break;
		}

		if(FLG)continue;

		for(int i = 0; i < num_info; i++){

			check_table[check_index][i] = calc_info[i].ch;
		}

		check_index++;

		makeSection(0,num_info,0);

	}while(next_permutation(perm_table,perm_table+num_info));

	//区間の集合を走査し、その割り当て方ごとに、場合の数を計上する
	double num_pattern = 0;

	for(int i = 0; i < SECTION.size(); i++){

		int num_section = SECTION[i].size();

		for(int k = 0; k < num_section; k++){

			section[k] = SECTION[i][k];		}

		double base = 1;
		for(int k = 0; k < num_section; k++){
			for(int p = 0; p <= SECTION[i][k].maximum; p++){

				base *= nCm[N][SECTION[i][k].count_table[p]];
			}
		}

		for(int a = 0; a <= num_section; a++){
			for(int b = 0; b <= M; b++){
				dp[a][b] = -1;
			}
		}

		num_pattern += base*dfs(0,num_section,0); //数字の選び方*区間の割り当て方を加算
	}

	printf("%.10lf\n",num_pattern/num_all);
}

void makeTable(){

	nCm[0][0] = 1;
	for(ll n = 1; n <= 420; n++) {
		for (int m = 0; m <= 7; m++) {
			if(m > 0){
				nCm[n][m] = nCm[n-1][m]+nCm[n-1][m-1];
			}else{ //m == 0
				nCm[n][m] = 1;
			}
		}
	}
}

int main(){

	makeTable();

	while(true){

		scanf("%d %d %d",&N,&M,&L);
		if(N == 0 && M == 0 && L == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 3336
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Info{

	char ch;
	int maximum,count_table[7];
};

int table[7],work[7];
int N,M,L;
int check_index;
ll dp[8][61];
double nPk[421][8],nCm[421][8];
char pattern[7][10];
char check_table[5040][7];
vector<vector<Info>> SECTION;
Info info[7],calc_info[7],work_info[7],section[7];


//連続した数字の塊【区間】を0～M-1に当てはめる【最大L個】
ll dfs(int section_index,int num_section,int num_index){

	if(num_index == M){

		if(section_index < num_section){ //当てはめをしていない区間あり

			return 0;
		}else{

			return 1;
		}
	}

	if(dp[section_index][num_index] != -1){

		return dp[section_index][num_index];
	}

	ll ret = 0;

	//割り当てない
	ret += dfs(section_index,num_section,num_index+1);

	//割り当てる
	if(section_index < num_section){

		int tail = num_index+section[section_index].maximum;
		if(tail <= M-1){

			//★重複計上を防ぐため、区間と区間の間には少なくとも1つの空白を設ける★
			ret += dfs(section_index+1,num_section,min(M,tail+2));
		}
	}

	return dp[section_index][num_index] = ret;
}

void makeSection(int section_index,int num_info,int work_index){

	if(section_index == num_info){ //区間作成完了

		//既存区間と重複していないか調べる
		bool FLG = false;

		for(int i = 0; i < SECTION.size(); i++){
			FLG = true;
			if(SECTION[i].size() != work_index){ //区間の数が異なるならOK
				FLG = false;
				continue;
			}
			for(int k = 0; k < SECTION[i].size(); k++){
				if(SECTION[i][k].maximum != work_info[k].maximum){ //ある区間の長さが異なるならOK

					FLG = false;
					break;
				}
				for(int p = 0; p <= SECTION[i][k].maximum; p++){
					if(SECTION[i][k].count_table[p] != work_info[k].count_table[p]){ //ある数字の数が異なるならOK

						FLG = false;
						break;
					}
				}
				if(!FLG)break;
			}
			if(FLG)break;
		}

		if(FLG)return;

		vector<Info> vec;

		for(int i = 0; i < work_index; i++){

			vec.push_back(work_info[i]);
		}

		SECTION.emplace_back(vec);

		return;
	}

	//既存の区間と重なりを持つ場合
	for(int i = 0; i < work_index; i++){
		for(int merge_head = 0; merge_head <= work_info[i].maximum+1; merge_head++){

			if(merge_head+calc_info[section_index].maximum >= min(L,M))continue;

			//数字の個数がNを越えないか調べる
			bool FLG = true;
			for(int k = 0; merge_head+k <= work_info[i].maximum && k <= calc_info[section_index].maximum; k++){
				if(work_info[i].count_table[merge_head+k]+calc_info[section_index].count_table[k] > N){

					FLG = false;
					break;
				}
			}

			if(!FLG)continue;

			int pre_max = work_info[i].maximum;

			for(int k = 0; k <= calc_info[section_index].maximum; k++){
				work_info[i].count_table[merge_head+k] += calc_info[section_index].count_table[k];
				work_info[i].maximum = max(work_info[i].maximum,merge_head+k);
			}

			makeSection(section_index+1,num_info,work_index);

			//元に戻す
			for(int k = 0; k <= calc_info[section_index].maximum; k++){
				work_info[i].count_table[merge_head+k] -= calc_info[section_index].count_table[k];
			}
			work_info[i].maximum = pre_max;
		}
	}


	//新しい区間とする場合
	work_info[work_index] = calc_info[section_index];
	makeSection(section_index+1,num_info,work_index+1);
}


void func(){

	for(int i = 0; i < L; i++){

		scanf("%s",pattern[i]);
	}
	printf("\n");

	SECTION.clear();

	double num_all = nCm[N*M][L];

	/*patternに該当する場合の数を計上する*/

	//pattern情報を調べる
	int num_info = 0;
	for(int i = 0; i < 7; i++){
		for(int k = 0; k < 7; k++){
			info[i].count_table[k] = 0;
		}
	}

	for(int i = 0; i < L; i++){

		if(pattern[i][0] == '*'){ //独立させる

			info[num_info].ch = '*';
			info[num_info].maximum = 0;
			info[num_info].count_table[0] = 1;

			num_info++;

		}else{

			int index = -1;

			for(int k = 0; k < num_info; k++){

				if(info[k].ch == pattern[i][0]){

					index = k;
					break;
				}
			}

			if(index == -1){

				info[num_info].ch = pattern[i][0];
				info[num_info].maximum = 0;
				index = num_info;
				num_info++;
			}

			int num_plus = 0;

			for(int k = 1; pattern[i][k] == '+'; k++,num_plus++);

			info[index].count_table[num_plus] += 1; //a a a++ a++ a+++ 等
			info[index].maximum = max(info[index].maximum,num_plus);
		}
	}

	//patternにマッチする場合を数え上げる
	//★★★★異なる変数の間には、表すランクについての制約はない★★★★

	//区間の集合を作成する
	int perm_table[7];
	for(int i = 0; i < num_info; i++){
		perm_table[i] = i;
	}

	check_index = 0;

	do{

		for(int i = 0; i < num_info; i++){ //infoを固定すると計上漏れが発生する

			calc_info[i] = info[perm_table[i]];
		}

		bool FLG = false;

		//既に処理していないか調べる
		for(int i = 0; i < check_index; i++){
			FLG = true;
			for(int k = 0; k < num_info; k++){
				if(check_table[i][k] != calc_info[k].ch){
					FLG = false;
					break;
				}
			}
			if(FLG)break;
		}

		if(FLG)continue;

		for(int i = 0; i < num_info; i++){

			check_table[check_index][i] = calc_info[i].ch;
		}

		check_index++;

		makeSection(0,num_info,0);

	}while(next_permutation(perm_table,perm_table+num_info));

	//区間の集合を走査し、その割り当て方ごとに、場合の数を計上する
	double num_pattern = 0;

	for(int i = 0; i < SECTION.size(); i++){

		int num_section = SECTION[i].size();

		for(int k = 0; k < num_section; k++){

			section[k] = SECTION[i][k];		}

		double base = 1;
		for(int k = 0; k < num_section; k++){
			for(int p = 0; p <= SECTION[i][k].maximum; p++){

				base *= nCm[N][SECTION[i][k].count_table[p]];
			}
		}

		for(int a = 0; a <= num_section; a++){
			for(int b = 0; b <= M; b++){
				dp[a][b] = -1;
			}
		}

		num_pattern += base*dfs(0,num_section,0); //数字の選び方*区間の割り当て方を加算
	}

	printf("%.10lf\n",num_pattern/num_all);
}

void makeTable(){

	for(int n = 1; n <= 420; n++){

		nPk[n][0] = 1;
		nPk[n][1] = n;

		for(int k = 2; k <= 7; k++){

			nPk[n][k] = nPk[n][k-1]*(n-(k-1));
		}
	}

	nCm[0][0] = 1;
	for(ll n = 1; n <= 420; n++) {
		for (int m = 0; m <= 7; m++) {
			if(m > 0){
				nCm[n][m] = nCm[n-1][m]+nCm[n-1][m-1];
			}else{ //m == 0
				nCm[n][m] = 1;
			}
		}
	}
}

int main(){

	makeTable();

	while(true){

		scanf("%d %d %d",&N,&M,&L);
		if(N == 0 && M == 0 && L == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 3432
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define REP(i,n) for(int i=0; i<n; i++)
#define FOR(i,a,b) for(int i=a; i<b; i++)
#define FORR(i,a,b) for(int i=(int)b-1; i>=a; i--)

#define ALL(v) (v).begin(), (v).end()

using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<int>;
using vl = vector<ll>;

#define DEBUG(x) cerr<<#x<<": "<<(x)<<endl
#define CHMIN(a,b) (a)=min((a),(b))
#define CHMAX(a,b) (a)=max((a),(b))

void debug_vec(vi v){
    for(int x:v){
        fprintf(stderr,"%d,",x);
    }fprintf(stderr,"\n");
}

int n,m,l;
char hand[7][25];
int typ[7];
int pls[7];

bool ctn(vi &a, vi &pat){
    REP(i,a.size())if(a[i]<pat[i])return false;
    return true;
}

ll encode(const vi &v){
    ll ret = 0;
    REP(i,l){
        ret *= 256;
        ret += v[i];
    }
    return ret;
}
vi decode(ll x){
    vi v;
    REP(i,l){
        v.push_back(x%256);
        x/=256;
    }
    reverse(ALL(v));
    return v;
}

ll fact[14];
ll comb[525][14];

int main(){
    fact[0] = 1;
    FOR(i,1,14)fact[i]=i*fact[i-1];
    REP(i,525)REP(j,14){
        if(j>i)comb[i][j]=0;
        else if(i==j || j==0)comb[i][j]=1;
        else comb[i][j]=comb[i-1][j-1] + comb[i-1][j];
    }
    while(true){
        scanf("%d%d%d",&n,&m,&l);
        if(n+m+l==0)break;
        REP(i,l){
            fill(hand[i],hand[i]+25,'\0');
            scanf("%s",hand[i]);
        }
        // to asterisk
        int a=0,b=0,c=0,d=0;
        REP(i,l){
            char x = hand[i][0];
            if(x=='*'){
                d++;
                typ[i]=3;
                pls[i]=0;
            }else if(x=='a'){
                a++;
                typ[i]=0;
                pls[i]=strlen(hand[i])-1;
            }else if(x=='b'){
                b++;
                typ[i]=1;
                pls[i]=strlen(hand[i])-1;
            }else if(x=='c'){
                c++;
                typ[i]=2;
                pls[i]=strlen(hand[i])-1;
            }
        }
        if(a==1){
            REP(i,l)if(typ[i]==0)typ[i]=3,pls[i]=0;
            a=0;
        }
        if(b==1){
            REP(i,l)if(typ[i]==1)typ[i]=3,pls[i]=0;
            b=0;
        }
        if(c==1){
            REP(i,l)if(typ[i]==2)typ[i]=3,pls[i]=0;
            c=0;
        }
        // sort
        if(a==0){
            // a<-c
            REP(i,l)if(typ[i]==2)typ[i]=0;
            a=c;c=0;
        }
        if(a==0){
            // a<-b
            REP(i,l)if(typ[i]==1)typ[i]=0;
            a=b;b=0;
        }
        if(b==0){
            // b<-c
            REP(i,l)if(typ[i]==2)typ[i]=1;
            b=c;c=0;
        }
        // REP(i,l)printf("%d %d\n",typ[i],pls[i]);
        // split
        if(a==0){
            // all asterisk
            puts("1.0000000000");
        }else if(b==0){
            // single char
            vi pat(7,0);
            int mx = 0;
            REP(i,l)if(typ[i]==0)CHMAX(mx,pls[i]);
            REP(i,l)if(typ[i]==0){
                pat[6-mx+pls[i]]++;
            }
            // REP(i,7)printf("%d ",pat[i]);puts("");
            map<vi,ll> dp[2][8][2];
            dp[0][0][0][vi(7,0)] = 1;
            int cur = 0;
            REP(t,m){
                int nxt = cur^1;
                REP(i,8)REP(j,2)dp[nxt][i][j].clear();
                REP(used,l+1)REP(flag,2)for(auto &P:dp[cur][used][flag]){
                    REP(use,n+1){
                        if(used+use>l)break;
                        vi nv(7);
                        REP(i,6)nv[i] = P.first[i+1];
                        nv[6] = use;
                        int nuse = used + use;
                        int nflag = flag || ctn(nv,pat);
                        dp[nxt][nuse][nflag][nv] += P.second * comb[n][use];
                    }
                }
                cur = nxt;
            }
            ll ans = 0;
            for(auto &P:dp[cur][l][1]){
                ans += P.second;
            }
            // DEBUG(ans);
            printf("%.10f\n",1.0*ans/comb[n*m][l]);
        }else{
            vector<vi> pats;
            REP(c,3){
                vi pat;
                REP(i,l)if(typ[i]==c){
                    while(pat.size() <= pls[i])pat.push_back(0);
                    pat[pls[i]]++;
                }
                if(pat.size()>0)pats.push_back(pat);
            }
            REP(i,l)if(typ[i]==3){
                pats.push_back(vi(1,1));
            }
            sort(ALL(pats));
            set<vector<vi>> S;
            stack<vector<vi>> T;
            do{
                S.insert(pats);
                T.push(pats);
            }while(next_permutation(ALL(pats)));
            while(T.size()){
                vector<vi> V = T.top(); T.pop();
                int nn = V.size();
                REP(i,nn-1){
                    vector<vi> NV;
                    REP(j,nn){
                        if(j==i){
                            // insert combine
                            NV.push_back(vi()); // dummy
                        }else if(j==i+1){
                            continue;
                        }else{
                            NV.push_back(V[j]);
                        }
                    }
                    vi x = V[i];
                    vi y = V[i+1];
                    int xl = x.size();
                    int yl = y.size();
                    // slide y
                    REP(j,xl+1){
                        vi z(max(xl,j+yl),0);
                        REP(k,xl)z[k]+=x[k];
                        REP(k,yl)z[j+k]+=y[k];
                        if(*max_element(ALL(z))>n)continue;
                        vector<vi> NNV = NV;
                        NNV[i] = z;
                        if(!S.count(NNV)){
                            S.insert(NNV);
                            T.push(NNV);
                        }
                    }
                    // slide x
                    FOR(j,1,yl+1){
                        vi z(max(j+xl,yl),0);
                        REP(k,xl)z[j+k]+=x[k];
                        REP(k,yl)z[k]+=y[k];
                        if(*max_element(ALL(z))>n)continue;
                        vector<vi> NNV = NV;
                        NNV[i] = z;
                        if(!S.count(NNV)){
                            S.insert(NNV);
                            T.push(NNV);
                        }
                    }
                }
            }
            ll total = comb[n*m][l];
            ll cnt = 0;
            for(vector<vi> pat:S){
                int nn = pat.size();
                // fprintf(stderr,"nn=%d\n",nn);
                ll mul = 1;
                int len = 0;
                for(vi V:pat){
                    // debug_vec(V);
                    len += V.size();
                    REP(i,V.size()){
                        mul *= comb[n][V[i]];
                        // fprintf(stderr, "(%d,%d)\n", n,V[i]);
                    }
                }
                // position: nn+1
                // num:      m-len-(nn-1)=m-len-nn+1
                if(m-len<nn-1)continue;
                // DEBUG(mul);
                // DEBUG(m-len+1);
                // DEBUG(nn);
                // DEBUG(comb[m-len+1][nn]);
                mul *= comb[m-len+1][nn];
                // DEBUG(mul);
                cnt += mul;
            }
            // DEBUG(cnt);
            // DEBUG(total);
            // if(cnt<0)return 0;
            printf("%.10f\n",1.0*cnt/total);
        }
        // }else if(c==0){
        //     // double char
        //     if(d<=2){
        //         // brute force
        //         ll total = comb[n*m][l];
        //         ll poyo = 0;
        //         unordered_set<ll> S;
        //         REP(x,m)REP(y,m)REP(z,m)REP(w,z+1){
        //             int aa[] = {x,y,z,w};
        //             vi v;
        //             int po = 0;
        //             REP(i,l){
        //                 if(typ[i]<3){
        //                     v.push_back(aa[typ[i]]+pls[i]);
        //                 }else{
        //                     v.push_back(aa[2+po]);
        //                     po++;
        //                 }
        //             }
        //             sort(ALL(v));
        //             if(v.back()>=m){
        //                 // DEBUG("!?");
        //                 continue;
        //             }
        //             int bef = -1;
        //             int cnt = 0;
        //             // ll pat = fact(l);
        //             ll pat = 1;
        //             REP(i,l){
        //                 if(v[i]==bef){
        //                     cnt++;
        //                     if(cnt>n)break;
        //                 }else{
        //                     // pat /= fact(cnt);
        //                     pat *= comb[n][cnt];
        //                     bef=v[i];
        //                     cnt=1;
        //                 }
        //             }
        //             if(cnt>n){
        //                 // DEBUG("!?");
        //                 continue;
        //             }
        //             // pat /= fact(cnt);
        //             pat *= comb[n][cnt];

        //             ll id = encode(v);
        //             if(S.count(id))continue;
        //             S.insert(id);
        //             poyo += pat;
        //         }
        //         printf("%.10f\n",1.0 * poyo / total);
        //     }else{
        //         // no brute-force
        //         int hori=0, vert=0;
        //         REP(c,2){
        //             int c0=0,c1=0;
        //             REP(i,l)if(typ[i]==c)(pls[i]==0?c0:c1)++;
        //             if(c0==2){
        //                 vert++;
        //             }else{
        //                 hori++;
        //             }
        //         }
        //         puts("not implemented");
        //     }
        // }else{
        //     // triple char
        //     // brute force
        //     ll total = comb[n*m][l];
        //     ll poyo = 0;
        //     unordered_set<ll> S;
        //     REP(x,m)REP(y,m)REP(z,m)REP(w,m){
        //         int aa[] = {x,y,z,w};
        //         vi v;
        //         REP(i,l){
        //             v.push_back(aa[typ[i]]+pls[i]);
        //         }
        //         sort(ALL(v));
        //         if(v.back()>=m){
        //             // DEBUG("!?");
        //             continue;
        //         }
        //         int bef = -1;
        //         int cnt = 0;
        //         // ll pat = fact(l);
        //         ll pat = 1;
        //         REP(i,l){
        //             if(v[i]==bef){
        //                 cnt++;
        //                 if(cnt>n)break;
        //             }else{
        //                 // pat /= fact(cnt);
        //                 pat *= comb[n][cnt];
        //                 bef=v[i];
        //                 cnt=1;
        //             }
        //         }
        //         if(cnt>n){
        //             // DEBUG("!?");
        //             continue;
        //         }
        //         // pat /= fact(cnt);
        //         pat *= comb[n][cnt];

        //         ll id = encode(v);
        //         if(S.count(id))continue;
        //         S.insert(id);
        //         poyo += pat;
        //     }
        //     printf("%.10f\n",1.0 * poyo / total);
        // }
    }
    return 0;
}
accuracy: 1
time_ms: 6860
memory_kb: 5028
final_rank: 19

code_snippet: //copied from http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=1635223#1
//my source code is http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=3712456#1

#include<stdio.h>
#include<algorithm>
using namespace std;
char in[10][10];
int pl[10];
int u[10][10];
int t3[10];
int q[10];
int used[10];
int L;
int dfs(int a){
    if(a==3){
        return 1;
    }
    if(u[a][0]==0)return dfs(a+1);
    for(int i=0;i<L;i++){
        if(used[i])continue;
        bool ok=true;
        for(int j=0;j<L;j++){
            int cnt=0;
            for(int k=0;k<L;k++){
                if(!used[k]&&q[k]==q[i]+j)cnt++;
            }
            if(cnt<u[a][j])ok=false;
        }
        if(ok){
            for(int j=0;j<L;j++){
                int cnt=0;
                for(int k=0;k<L;k++){
                    if(cnt==u[a][j])break;
                    if(!used[k]&&q[k]==q[i]+j){
                        cnt++;
                        used[k]=1;
                    }
                }
            }
            if(dfs(a+1))return 1;
            for(int j=0;j<L;j++){
                int cnt=0;
                for(int k=0;k<L;k++){
                    if(cnt==u[a][j])break;
                    if(used[k]&&q[k]==q[i]+j){
                        cnt++;
                        used[k]=0;
                    }
                }
            }
        }
    }
    return 0;
}
long long C[10][10];
int main(){
    int a,b,c;
    t3[0]=1;
    C[0][0]=1;
    for(int i=0;i<9;i++){
        for(int j=0;j<=i;j++){
            C[i+1][j]+=C[i][j];
            C[i+1][j+1]+=C[i][j];
        }
    }
    for(int i=1;i<10;i++)t3[i]=t3[i-1]*3;
    while(scanf("%d%d%d",&a,&b,&c),a){
        L=c;
        for(int i=0;i<10;i++)for(int j=0;j<10;j++)u[i][j]=0;
        for(int i=0;i<c;i++){
            scanf("%s",in[i]);
            pl[i]=0;
            for(int j=1;in[i][j];j++)pl[i]++;
            if(in[i][0]!='*')u[in[i][0]-'a'][pl[i]]++;
        }
    /*  for(int i=0;i<3;i++){
            for(int j=0;j<7;j++)printf("%d ",u[i][j]);
            printf("\n");
        }*/
        long long ret=0;
        for(int i=0;i<t3[c-1];i++){
            q[0]=0;
            for(int j=0;j<c;j++)used[j]=0;
            for(int j=1;j<c;j++){
                q[j]=q[j-1]+i%t3[j]/t3[j-1];
            }
            if(!dfs(0))continue;
            long long tmp=1;
            int now=0;
            int div=1;
            int num=1;
            for(int j=0;j<c;j++){
                if(j&&q[j]!=q[j-1]){
                    tmp*=C[a][now];
                    now=1;
                    num++;
                    if(q[j-1]+1<q[j])div++;
                }else now++;
            }
            tmp*=C[a][now];
            int un=b-num;
            if(un<div-1)continue;
            un-=div-1;
            for(int j=0;j<div;j++){
                tmp*=(un+div-j);
                tmp/=(j+1);
            }
        //  for(int j=0;j<c;j++)printf("%d ",q[j]);
        //  printf(": %lld\n",tmp);
            ret+=tmp;
        }
        long long total=1;
        for(int i=0;i<c;i++){
            total*=(a*b-i);
            total/=(i+1);
        }
        printf("%.12f\n",(double)ret/total);
    }
}
accuracy: 1
time_ms: 50
memory_kb: 2708
final_rank: 4

code_snippet: //copied from http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=1635223#1
//my source code is http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=3712456#1

#include<stdio.h>
#include<algorithm>
using namespace std;
char in[10][10];
int pl[10];
int u[10][10];
int t3[10];
int q[10];
int used[10];
int L;
int dfs(int a){
    if(a==3){
        return 1;
    }
    if(u[a][0]==0)return dfs(a+1);
    for(int i=0;i<L;i++){
        if(used[i])continue;
        bool ok=true;
        for(int j=0;j<L;j++){
            int cnt=0;
            for(int k=0;k<L;k++){
                if(!used[k]&&q[k]==q[i]+j)cnt++;
            }
            if(cnt<u[a][j])ok=false;
        }
        if(ok){
            for(int j=0;j<L;j++){
                int cnt=0;
                for(int k=0;k<L;k++){
                    if(cnt==u[a][j])break;
                    if(!used[k]&&q[k]==q[i]+j){
                        cnt++;
                        used[k]=1;
                    }
                }
            }
            if(dfs(a+1))return 1;
            for(int j=0;j<L;j++){
                int cnt=0;
                for(int k=0;k<L;k++){
                    if(cnt==u[a][j])break;
                    if(used[k]&&q[k]==q[i]+j){
                        cnt++;
                        used[k]=0;
                    }
                }
            }
        }
    }
    return 0;
}
long long C[10][10];
int main(){
    int a,b,c;
    t3[0]=1;
    C[0][0]=1;
    for(int i=0;i<9;i++){
        for(int j=0;j<=i;j++){
            C[i+1][j]+=C[i][j];
            C[i+1][j+1]+=C[i][j];
        }
    }
    for(int i=1;i<10;i++)t3[i]=t3[i-1]*3;
    while(scanf("%d%d%d",&a,&b,&c),a){
        L=c;
        for(int i=0;i<10;i++)for(int j=0;j<10;j++)u[i][j]=0;
        for(int i=0;i<c;i++){
            scanf("%s",in[i]);
            pl[i]=0;
            for(int j=1;in[i][j];j++)pl[i]++;
            if(in[i][0]!='*')u[in[i][0]-'a'][pl[i]]++;
        }
    /*  for(int i=0;i<3;i++){
            for(int j=0;j<7;j++)printf("%d ",u[i][j]);
            printf("\n");
        }*/
        long long ret=0;
        for(int i=0;i<t3[c-1];i++){
            q[0]=0;
            for(int j=0;j<c;j++)used[j]=0;
            for(int j=1;j<c;j++){
                q[j]=q[j-1]+i%t3[j]/t3[j-1];
            }
            if(!dfs(0))continue;
            long long tmp=1;
            int now=0;
            int div=1;
            int num=1;
            for(int j=0;j<c;j++){
                if(j&&q[j]!=q[j-1]){
                    tmp*=C[a][now];
                    now=1;
                    num++;
                    if(q[j-1]+1<q[j])div++;
                }else now++;
            }
            tmp*=C[a][now];
            int un=b-num;
            if(un<div-1)continue;
            un-=div-1;
            for(int j=0;j<div;j++){
                tmp*=(un+div-j);
                tmp/=(j+1);
            }
        //  for(int j=0;j<c;j++)printf("%d ",q[j]);
        //  printf(": %lld\n",tmp);
            ret+=tmp;
        }
        long long total=1;
        for(int i=0;i<c;i++){
            total*=(a*b-i);
            total/=(i+1);
        }
        printf("%.12f\n",(double)ret/total);
    }
}
accuracy: 1
time_ms: 50
memory_kb: 2752
final_rank: 5

code_snippet: #include<bits/stdc++.h>
using namespace std;

using LL = long long;
using D = double;

LL N, M, L;
vector<vector<LL>> CARD;

LL partition(LL n, LL k) {
  static map<pair<LL, LL>, LL> memo;
  auto m = make_pair(n, k);
  if(memo.count(m)) return memo[m];
  if(k == 1) return 1;
  LL res = 0;
  for(LL i = 1; k - 1 <= n - i; ++i) res += partition(n - i, k - 1);
  return memo[m] = res;
}

LL combination(LL n, LL r) {
  static map<pair<LL, LL>, LL> memo;
  auto m = make_pair(n, r);
  if(memo.count(m)) return memo[m];
  return memo[m] = (r % n == 0 ? 1 : combination(n - 1, r - 1) + combination(n - 1, r));
}

bool valid(auto c, auto& hand) {
  if(c == 3) return true;

  if(CARD[c].empty()) return valid(c + 1, hand);

  for(auto i = 0; i + CARD[c].size() - 1 < hand.size(); ++i) {
    bool ok = true;
    for(auto j = 0; j < CARD[c].size(); ++j) if(hand[i + j] < CARD[c][j]) ok = false;
    if(!ok) continue;

    for(auto j = 0; j < CARD[c].size(); ++j) hand[i + j] -= CARD[c][j];
    ok = valid(c + 1, hand);
    for(auto j = 0; j < CARD[c].size(); ++j) hand[i + j] += CARD[c][j];

//     if(ok)cout<<"OK"<<endl;
    if(ok) return true;
  }
  return false;
}

LL count(auto& hand) {
//   return 1;
  LL res = 1;
  LL zero = 0;
  for(auto i: hand) {
    res *= combination(N, i);
    if(i == 0) ++zero;
  }
  if(zero) res *= partition(M - (hand.size() - zero), zero);
  return res;
}

LL dfs(auto& hand, LL remain, LL last) {
  LL res = 0;

  if(hand.size() > M) return 0;

  if(remain == 0) {
//     for(auto i:hand)cout<<" "<<i;cout<<endl;
    if(count(begin(hand), end(hand), 0ll) == 0) {
      if(hand.size() == M) if(valid(0, hand)) res += count(hand);
    } else {
      if(valid(0, hand)) res += count(hand);
    }
  }

  for(auto i = 0ll; i <= min(N, remain); ++i) {
    if(i == 0 && last == 0) continue;
    hand.emplace_back(i);
    res += dfs(hand, remain - i, i);
    hand.pop_back();
  }

  return res;
}

D solve() {
  for(auto c: CARD) if(c.size() > M) return 0;

  vector<LL> hand;
  D fit = dfs(hand, L, -1);
  D total = combination(N * M, L);
//   return fit;
  return fit / total;
}

int main() {
  while(cin >> N >> M >> L, N | M | L) {
    CARD = vector<vector<LL>>(3);

    for(auto i = 0; i < L; ++i) {
      string s;
      cin >> s;

      if(s.front() == '*') continue;

      auto& c = CARD[s.front() - 'a'];
      c.resize(max(c.size(), s.size()), 0);
      ++c[s.size() - 1];
    }

    cout << setprecision(10) << fixed << solve() << endl;
  }
}
accuracy: 1
time_ms: 40
memory_kb: 3448
final_rank: 7

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
char in[10][10];
int pl[10];
int u[10][10];
int t3[10];
int q[10];
int used[10];
int L;
int dfs(int a){
	if(a==3){
		return 1;
	}
	if(u[a][0]==0)return dfs(a+1);
	for(int i=0;i<L;i++){
		if(used[i])continue;
		bool ok=true;
		for(int j=0;j<L;j++){
			int cnt=0;
			for(int k=0;k<L;k++){
				if(!used[k]&&q[k]==q[i]+j)cnt++;
			}
			if(cnt<u[a][j])ok=false;
		}
		if(ok){
			for(int j=0;j<L;j++){
				int cnt=0;
				for(int k=0;k<L;k++){
					if(cnt==u[a][j])break;
					if(!used[k]&&q[k]==q[i]+j){
						cnt++;
						used[k]=1;
					}
				}
			}
			if(dfs(a+1))return 1;
			for(int j=0;j<L;j++){
				int cnt=0;
				for(int k=0;k<L;k++){
					if(cnt==u[a][j])break;
					if(used[k]&&q[k]==q[i]+j){
						cnt++;
						used[k]=0;
					}
				}
			}
		}
	}
	return 0;
}
long long C[10][10];
int main(){
	int a,b,c;
	t3[0]=1;
	C[0][0]=1;
	for(int i=0;i<9;i++){
		for(int j=0;j<=i;j++){
			C[i+1][j]+=C[i][j];
			C[i+1][j+1]+=C[i][j];
		}
	}
	for(int i=1;i<10;i++)t3[i]=t3[i-1]*3;
	while(scanf("%d%d%d",&a,&b,&c),a){
		L=c;
		for(int i=0;i<10;i++)for(int j=0;j<10;j++)u[i][j]=0;
		for(int i=0;i<c;i++){
			scanf("%s",in[i]);
			pl[i]=0;
			for(int j=1;in[i][j];j++)pl[i]++;
			if(in[i][0]!='*')u[in[i][0]-'a'][pl[i]]++;
		}
	/*	for(int i=0;i<3;i++){
			for(int j=0;j<7;j++)printf("%d ",u[i][j]);
			printf("\n");
		}*/
		long long ret=0;
		for(int i=0;i<t3[c-1];i++){
			q[0]=0;
			for(int j=0;j<c;j++)used[j]=0;
			for(int j=1;j<c;j++){
				q[j]=q[j-1]+i%t3[j]/t3[j-1];
			}
			if(!dfs(0))continue;
			long long tmp=1;
			int now=0;
			int div=1;
			int num=1;
			for(int j=0;j<c;j++){
				if(j&&q[j]!=q[j-1]){
					tmp*=C[a][now];
					now=1;
					num++;
					if(q[j-1]+1<q[j])div++;
				}else now++;
			}
			tmp*=C[a][now];
			int un=b-num;
			if(un<div-1)continue;
			un-=div-1;
			for(int j=0;j<div;j++){
				tmp*=(un+div-j);
				tmp/=(j+1);
			}
		//	for(int j=0;j<c;j++)printf("%d ",q[j]);
		//	printf(": %lld\n",tmp);
			ret+=tmp;
		}
		long long total=1;
		for(int i=0;i<c;i++){
			total*=(a*b-i);
			total/=(i+1);
		}
		printf("%.12f\n",(double)ret/total);
	}
}
accuracy: 1
time_ms: 70
memory_kb: 1072
final_rank: 1

code_snippet: #include <bits/stdc++.h>

#ifdef LOCAL
#include "dump.hpp"
#else
#define dump(...)
#endif

using namespace std;

constexpr int MAX_N = 7;
constexpr int MAX_M = 60;
constexpr int MAX_L = 7;

int N, M, L;

map<char, int> c;
int kind[MAX_L];
int num[MAX_L];
int hand[MAX_L];

long long memo[MAX_N * MAX_M + 1][MAX_L + 1];
long long combination(int n, int k) {
	if(k == 0 || n == k) return 1;
	auto &res = memo[n][k];
	if(res) return res;
	return res = combination(n - 1, k - 1) + combination(n - 1, k);
}

bool match() {
	vector<int> value(c.size());
	vector<int> card(hand, hand + L);

	do {
		fill(begin(value), end(value), -1);
		for(int i = 0; i < L; ++i) {
			if(kind[i] == -1) continue;

			if(value[kind[i]] == -1) {
				if(card[i] <= num[i]) goto fail;
				value[kind[i]] = card[i] - num[i];
			}
			else {
				if(value[kind[i]] != card[i] - num[i]) goto fail;
			}
		}
		return true;

	fail:;
	} while(next_permutation(begin(card), end(card)));

	return false;
}

long long calc() {
	if(!match()) return 0;

	long long res = 1;
	map<int, int> cnt;
	for(int i = 0; i < L; ++i) {
		++cnt[hand[i]];
	}

	for(const auto &e : cnt) {
		res *= combination(N, e.second);
	}

	int select = 1;
	for(int i = 1; i < L; ++i) {
		if(hand[i - 1] + 1 <  hand[i]) ++select;
	}

	res *= combination(M - (hand[L - 1] - select), select);
	return res;
}

long long dfs(int idx, int len) {
	if(idx == L) return calc();

	long long res = 0;
	for(int i = 0; i < 3; ++i) {
		if(i == 0 && len == N) continue;
		if(hand[0] + M <= hand[idx - 1] + i) break;
		hand[idx] = hand[idx - 1] + i;
		res += dfs(idx + 1, (i ? 1 : len + 1));
	}
	return res;
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	//cout.precision(10);
	cout.precision(9);

	while(cin >> N >> M >> L && N) {
		c.clear();

		for(int i = 0; i < L; ++i) {
			string pattern;
			cin >> pattern;

			if(pattern == "*") {
				kind[i] = -1;
			}
			else {
				if(!c.count(pattern[0])) c.insert({pattern[0], c.size()});
				kind[i] = c[pattern[0]];
				num[i] = pattern.size() - 1;
			}
		}

		dump(c);
		hand[0] = 1;
		const auto ans = (long double)dfs(1, 1) / combination(N * M, L);
		cout << ans << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 1420
memory_kb: 1324
final_rank: 9

code_snippet: #define _USE_MATH_DEFINES
#define _CRT_SECURE_NO_DEPRECATE

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <limits>
#include <cfloat>
#include <ctime>
#include <cassert>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <list>
#include <iomanip>
#include <fstream>
#include <iterator>
#include <bitset>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pii;
typedef pair<ll, ll> Pll;

#define FOR(i,n) for(int i = 0; i < (n); i++)
#define sz(c) ((int)(c).size())
#define ten(x) ((int)1e##x)
#define tenll(x) ((ll)1e##x)

// #pragma comment(linker,"/STACK:36777216")

template<class T> void chmax(T& l, const T r) { l = max(l, r); }
template<class T> void chmin(T& l, const T r) { l = min(l, r); }
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T extgcd(T a, T b, T& x, T& y) { for (T u = y = 1, v = x = 0; a;) { T q = b / a; swap(x -= q * u, u); swap(y -= q * v, v); swap(b -= q * a, a); } return b; }
template<class T> T mod_inv(T a, T m) { T x, y; extgcd(a, m, x, y); return (m + x % m) % m; }
ll mod_pow(ll a, ll n, ll mod) { ll ret = 1; ll p = a % mod; while (n) { if (n & 1) ret = ret * p % mod; p = p * p % mod; n >>= 1; } return ret; }

#ifdef _WIN32
#   define mygc(c) (c)=getchar()
#   define mypc(c) putchar(c)
#else
#   define mygc(c) (c)=getchar_unlocked()
#   define mypc(c) putchar_unlocked(c)
#endif

void reader(int& x) { int k, m = 0; x = 0; for (;;) { mygc(k); if (k == '-') { m = 1; break; }if ('0' <= k&&k <= '9') { x = k - '0'; break; } }for (;;) { mygc(k); if (k<'0' || k>'9')break; x = x * 10 + k - '0'; }if (m) x = -x; }
void reader(ll& x) { int k, m = 0; x = 0; for (;;) { mygc(k); if (k == '-') { m = 1; break; }if ('0' <= k&&k <= '9') { x = k - '0'; break; } }for (;;) { mygc(k); if (k<'0' || k>'9')break; x = x * 10 + k - '0'; }if (m) x = -x; }
int reader(char c[]) { int i, s = 0; for (;;) { mygc(i); if (i != ' '&&i != '\n'&&i != '\r'&&i != '\t'&&i != EOF) break; }c[s++] = i; for (;;) { mygc(i); if (i == ' ' || i == '\n' || i == '\r' || i == '\t' || i == EOF) break; c[s++] = i; }c[s] = '\0'; return s; }
template <class T, class S> void reader(T& x, S& y) { reader(x); reader(y); }
template <class T, class S, class U> void reader(T& x, S& y, U& z) { reader(x); reader(y); reader(z); }
template <class T, class S, class U, class V> void reader(T& x, S& y, U& z, V & w) { reader(x); reader(y); reader(z); reader(w); }

void writer(int x, char c) { int s = 0, m = 0; char f[10]; if (x<0)m = 1, x = -x; while (x)f[s++] = x % 10, x /= 10; if (!s)f[s++] = 0; if (m)mypc('-'); while (s--)mypc(f[s] + '0'); mypc(c); }
void writer(ll x, char c) { int s = 0, m = 0; char f[20]; if (x<0)m = 1, x = -x; while (x)f[s++] = x % 10, x /= 10; if (!s)f[s++] = 0; if (m)mypc('-'); while (s--)mypc(f[s] + '0'); mypc(c); }
void writer(const char c[]) { int i; for (i = 0; c[i] != '\0'; i++)mypc(c[i]); }
void writer(const char x[], char c) { int i; for (i = 0; x[i] != '\0'; i++)mypc(x[i]); mypc(c); }
template<class T> void writerLn(T x) { writer(x, '\n'); }
template<class T, class S> void writerLn(T x, S y) { writer(x, ' '); writer(y, '\n'); }
template<class T, class S, class U> void writerLn(T x, S y, U z) { writer(x, ' '); writer(y, ' '); writer(z, '\n'); }
template<class T> void writerArr(T x[], int n) { if (!n) { mypc('\n'); return; }FOR(i, n - 1)writer(x[i], ' '); writer(x[n - 1], '\n'); }
template<class T> void writerArr(vector<T>& v) { if (sz(v)) writerArr(&v[0], sz(v)); else writer("\n"); }

const int NCK = 500;
double nck[NCK + 1][NCK + 1];
void calc_nck(){
	FOR(i, NCK){
		nck[i][0] = nck[i][i] = 1;
		for (int j = 1; j <= i; j++) {
			nck[i + 1][j] = (nck[i][j - 1] + nck[i][j]);
		}
	}
}

int n, m, l;
int pattern[3][7];
int ast;
double ans;

void check(const vector<vector<int>>& v){

	int x[60] = {};
	int mx = 0;
	FOR(i, sz(v)){
		FOR(j, sz(v[i])){
			x[mx++] = v[i][j];
		}
		mx++;
	}
	FOR(a, mx) FOR(b, mx) FOR(c, mx){
		int y[60] = {};
		FOR(i, 7){
			y[a + i] += pattern[0][i];
			y[b + i] += pattern[1][i];
			y[c + i] += pattern[2][i];
		}
		bool ok = true;
		FOR(i, 50) {
			if (x[i] < y[i]) {
				ok = false;
				break;
			}
		}
		if (ok) {
			double add = 1;
			int z = sz(v) - 1;
			for (auto& v1 : v){
				z += sz(v1) - 1;
				for (auto i : v1) {
					add *= nck[n][i];
				}
			}
			if (m - z <= 0) return;
			add *= nck[m - z][sz(v)];
			ans += add;
			//if (add > 0) {
			//	for (auto& v1 : v) {
			//		printf("{");
			//		for (auto i : v1) {
			//			printf("%d ", i);
			//		}
			//		printf("} ");
			//	}
			//	printf("%f\n", add);
			//}
			return;
		}
	}
}

void dfs(vector<vector<int>>& v,int rem){
	if (rem == 0) {
		check(v);
		return;
	}
	if (sz(v.back()) != 0) {
		v.emplace_back();
		dfs(v, rem);
		v.pop_back();
	}
	FOR(i, rem){
		if (i + 1 > n) break;
		v.back().push_back(i + 1);
		dfs(v, rem - i - 1);
		v.back().pop_back();
	}
}


void solve(){
	vector<vector<int>> v(1);
	dfs(v, l);
	ans /= nck[n*m][l];
}

int main(){
	calc_nck();
	while (cin >> n >> m >> l, n) {
		ans = 0;
		ast = 0;
		memset(pattern, 0, sizeof(pattern));
		FOR(i, l){
			string s; cin >> s;
			if (s[0] != '*') pattern[s[0] - 'a'][sz(s) - 1]++;
			else ast++;
		}
		solve();
		printf("%.10lf\n", ans);
	}
}
accuracy: 1
time_ms: 1940
memory_kb: 3208
final_rank: 17

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <algorithm>
#include <cstring>
#include <functional>
#include <cmath>
#include <complex>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);++i)
#define rep1(i,n) for(int i=1;i<=(n);++i)
#define all(c) (c).begin(),(c).end()
#define fs first
#define sc second
#define pb push_back
#define show(x) cout << #x << " " << x << endl
typedef long long ll;
int N,M,L,w;
vector<int> cs[3];
int p3[8];
ll C[421][421];
bool acc(int id,int* mycnt){
	if(id>60) return false;
	mycnt[id]++;
	return true;
}
int main(){
	p3[0]=1;
	rep(i,7) p3[i+1]=p3[i]*3;
	rep(i,421){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<min(i,8);j++) C[i][j]=C[i-1][j-1]+C[i-1][j];
	}
	while(true){
		cin>>N>>M>>L;
		if(N==0) break;
		rep(i,3) cs[i].clear();
		w=0;
		rep(i,L){
			string s;
			cin>>s;
			if(s[0]=='*') w++;
			else cs[s[0]-'a'].pb(s.size()-1);
		}
		if(cs[0].empty()&&!cs[1].empty()) swap(cs[0],cs[1]);
		if(cs[1].empty()&&!cs[2].empty()) swap(cs[1],cs[2]);
		if(cs[0].empty()&&!cs[2].empty()) swap(cs[0],cs[2]);
		int n=3;
		if(cs[2].empty()) n=2;
		if(cs[1].empty()) n=1;
		if(cs[0].empty()) n=3;
		ll ans=0;
		rep(i,p3[L-1]){
			int a[8]={},e[8]={},tmp=i,cnt[61]={};
			int gap=0,eq=0;
			rep(j,L-1){
				a[j]=tmp%3;
				tmp/=3;
				if(a[j]==2) gap++;
				if(a[j]==0) eq++;
			}
//			if(gap>=n) continue;
			rep(j,L-1){
				if(a[j]==2){
					e[j+1]=(e[j]/10+1)*10;
				}else{
					e[j+1]=e[j]+a[j];
				}
			}
			rep(j,L) cnt[e[j]]++;
			bool can=0;
			rep(j,61) if(cnt[j]>N) goto hoge;
			rep(j,L) rep(k,L) rep(h,L){
				int mycnt[61]={};
				bool ok=1;
				rep(jj,cs[0].size()) if(!acc(e[j]+cs[0][jj],mycnt)) ok=0;
				rep(kk,cs[1].size()) if(!acc(e[k]+cs[1][kk],mycnt)) ok=0;
				rep(hh,cs[2].size()) if(!acc(e[h]+cs[2][hh],mycnt)) ok=0;
				ll co=1;
				rep(p,61){
					if(cnt[p]<mycnt[p]) ok=0;
				}
				if(ok){
					can=1;
					goto hoge;
				}
			}
			hoge:
			if(can){
				ll co=1;
				rep(p,61) co*=C[N][cnt[p]];
//				printf("%d,%d,%d  ->  co=%lld\n",a[2],a[1],a[0],co);
//				show(M-(L-1-eq));
//				show(gap+1);
				if(M-(L-1-eq)<0||M-(L-1-eq)<gap+1) continue;
//				printf("%d,%d,%d  ->  narabe=%lld\n",a[0],a[1],a[2],C[M-(L-1-eq)][gap+1]);
				co*=C[M-(L-1-eq)][gap+1];
				ans+=co;
//				printf("%d,  %lld\n",i,co);
			}else{
//				printf("%d,no\n",i);
			}
		}
//		printf("ans=%lld\nC[][]=%lld\n",ans,C[N*M][L]);
		printf("%.12f\n",(double)ans/C[N*M][L]);
	}
}
accuracy: 1
time_ms: 2520
memory_kb: 2648
final_rank: 18

code_snippet: #include<cstdio>
#include<vector>
#include<string>
#include<iomanip>
#include<iostream>
#include<algorithm>

using namespace std;

vector<int> a[3];

void parse(string str){
	if(str[0]=='*'){
//		star++;
	}else{
		int cnt=str.size()-1;
		int id=str[0]-'a';
		a[id].push_back(cnt);
	}
}

int dif[7];
int val[7];
int L;

bool used[7];

int N,M;

bool dfs(int id){
	if(id==3){
		return true;
	}
	for(int i=0;i<L;i++){
		vector<int> tmp;
		int k=0;
		int x=val[i];
		for(int j=i;j<L;j++){
			if(k==a[id].size()) break;
			if(used[j]) continue;
			if(val[j]==x+a[id][k]){
				tmp.push_back(j);
				k++;
			}
		}
		if(k!=a[id].size()){
			continue;
		}
		for(int j=0;j<tmp.size();j++){
			used[tmp[j]]=true;
		}
		bool flg=dfs(id+1);
		if(flg) return true;
		for(int j=0;j<tmp.size();j++){
			used[tmp[j]]=false;
		}
	}
	return false;
}

bool check(){
	for(int i=0;i+N<L;i++){
		if(val[i]==val[i+N]) return false;
	}
	if(val[L-1]-val[0]>M-1) return false;
	for(int i=0;i<L;i++) used[i]=false;
//	printf("dfs\n");
	bool flg=dfs(0);
	return flg;
}

double C(int n,int r){
	if(r<0||r>n) return 0;
	double res=1;
	for(int i=1;i<=r;i++){
		res*=(n-i+1);
		res/=i;
	}
	return res;
}

double res;

void calc(){
//	printf("calc ");
	val[0]=0;
	for(int i=1;i<L;i++){
		val[i]=val[i-1]+dif[i-1];
	}
//	for(int i=0;i<L;i++) printf("%d ",val[i]);
//	printf("\n");
	bool flg=check();
	if(flg==false) return;
	double all=C(N*M,L);
	double cur=0;
	int cnt=0;
	for(int i=0;i<L-1;i++) if(dif[i]==2) cnt++;
	int sum=0;
	for(int i=0;i<L-1;i++) if(dif[i]!=2) sum+=dif[i];
//	printf("%d %d\n",cnt,sum);
	if(cnt==0){
		cur=M-sum;
	}else{
		for(int i=cnt*2;i<=M-1-sum;i++){
			double ad=C(i-cnt-1,cnt-1);
			ad*=(M-sum-i);
			cur+=ad;
//			printf("+=(%d %d)=%f\n",i-cnt-1,cnt-1,C(i-cnt-1,cnt-1));
		}
	}
	for(int i=0;i<L;i++){
		if(i!=0&&dif[i-1]==0) continue;
		int num=0;
		for(int j=i;j<L;j++){
			if(val[i]==val[j]) num++;
			else break;
		}
		cur*=C(N,num);
	}
//	printf("res+=%f\n",cur/all);
	res+=cur/all;
}

void dfs2(int i){
	if(i==L-1){
		calc();
		return;
	}
	for(int j=0;j<=2;j++){
		dif[i]=j;
		dfs2(i+1);
	}
}

double solve(){
	if(L==1) return 1;
	res=0;
	dfs2(0);
	return res;
}

void init(){
	for(int i=0;i<3;i++) a[i].clear();
}

int main(){
	int T=1;
	while(true){
		init();
		cin>>N>>M>>L;
		if(N==0) break;
		for(int i=0;i<L;i++){
			string str;
			cin>>str;
			parse(str);
		}
		for(int i=0;i<3;i++) sort(a[i].begin(),a[i].end());
//		for(int i=0;i<3;i++){
//			for(int j=0;j<a[i].size();j++) printf("%d ",a[i][j]);
//			printf("\n");
//		}
		double ans=solve();
	//	cout<<setprecision(9)<<ans<<"\n";
	//	printf("case %d %.9f\n",T,ans);
		printf("%.9f\n",ans);
		T++;
//		if(T==2) break;
	}
	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 1268
final_rank: 3

code_snippet: #include <string> 
#include <algorithm> 
#include <cfloat> 
#include <climits> 
#include <cmath> 
#include <complex> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <functional> 
#include <iostream> 
#include <map> 
#include <memory> 
#include <queue> 
#include <set> 
#include <sstream> 
#include <stack> 
#include <utility> 
#include <vector> 

#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define ALL(x) (x).begin(),(x).end() 
typedef long long ll;
using namespace std; 
const double eps = 1e-10;

ll comb[450][10];
int N, M, L, W;
string s[10];
vector<vector<int> > nums;

bool check(int k, vector<int> &hand){
    if(k == nums.size()) return true;
    int sz = nums[k].size();
    for(int i = 1; i + sz <= hand.size(); ++i){
        bool over = false;
        for(int j = 0; j < sz; ++j){
            hand[i+j] -= nums[k][j];
            over |= hand[i+j] < 0;
        }
        bool res = false;
        if(!over) res = check(k+1, hand);
        for(int j = 0; j < sz; ++j) hand[i+j] += nums[k][j];
        if(res) return true;
    }
    return false;
}
void print(const vector<int> &hand){
    cout << "h";
    for(int i = 1; i < hand.size(); ++i)
        cout << hand[i];
    cout << endl;
}
ll dfs(int r, vector<int> &hand){
    ll res = 0;
    if(hand.size() > M+1) return 0;
    if(r == 0 && check(0, hand)){
        res = 1;
        int zr = 0;
        for(int i = 1; i < hand.size(); ++i){
            if(hand[i]) res *= comb[N][hand[i]];
            else        zr++;
        }
        if(zr){
            int deck = M - (hand.size() - 1 - zr);
            res *= comb[deck-1][zr-1];
        }
        else if(hand.size() != M+1) res = 0;
        // print(hand);
        // cout << res << endl;
    }
    if(r > 0 || hand.back()){
        for(int i = hand.back()?0:1; i<=r && i<=N; ++i){
            hand.push_back(i);
            res += dfs(r-i, hand);
            hand.pop_back();
        }
    }
    return res;
}
int main(){
    memset(comb, 0, sizeof(comb));
    for(int i = 0; i < 450; ++i){
        comb[i][0] = 1;
        for(int j = 1; j <= min(i,9); ++j)
            comb[i][j] = comb[i-1][j-1] + comb[i-1][j];
    }
    for(;;){
        cin >> N >> M >> L;
        if(N == 0) return 0;
        nums.assign(3, vector<int>());
        for(int i = 0; i < L; ++i){
            cin >> s[i];
            if(s[i][0] != '*'){
                vector<int> &v = nums[s[i][0]-'a'];
                if(v.size() < s[i].size()) v.resize(s[i].size());
                v[s[i].size()-1]++;
            }
        }
        sort(ALL(nums)); reverse(ALL(nums));
        while(!nums.empty() && nums.back().empty()) nums.pop_back();
        vector<int> hand(1, -1);
        double res = (double)dfs(L, hand) / comb[N*M][L];
        printf("%.10f\n", res);
    }
}
accuracy: 1
time_ms: 30
memory_kb: 1312
final_rank: 2

code_snippet: #include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}

const int INF = 1<<28;
const double EPS = 1e-8;
const int MOD = 1000000007;


int N, M, L;

// O(n^2)で<=nのコンビネーションを作る
// (パスカルの三角形)
ll C[1010][1010];

void make_C(){
    memset(C, 0, (int)sizeof(C));    
    for(int i = 0; i < 1010; i++){
        C[i][0] = C[i][i] = 1;
        for(int j = 1; j < i; j++) C[i][j] = C[i-1][j-1] + C[i-1][j];
    }
}
vector<vi> seqs;
int check(const vi &hand, vector<vi> seqs){
	if(seqs.empty()) return 0;
	vi tar = seqs.back();
	int res = 0;
	REP(i, seqs.size()) res += accumulate(ALL(seqs[i]), 0);
	seqs.pop_back();
	REP(i, hand.size()){
		if(i && hand[i-1] == hand[i]) continue;
		vi next = hand;
		int base = hand[i];
		int f = 0;
		REP(d, tar.size()){
			REP(i, tar[d]){
				auto it = find(ALL(next), base + d);
				if(it == next.end()){
					f++;
				}else next.erase(it);
			}
		}
		if(res > f) res = min(res, f + check(next, seqs));
		if(res == 0) return 0;
	}
	return res;
}

vector<int> compress(const vi &hand, const int tail){
	if(hand.empty()) return vector<int>();
	vector<int> res;
	int base = hand[0];
	int t = 1;
	for(int i=1;i<hand.size();i++){
		if(hand[i] - hand[i-1] > 1){
			res.push_back(t);
			t = 1;
			base = hand[i];
		}else{
			t += 1<<(3*(hand[i] - base));
		}
	}
	res.push_back(t);
	sort(res.begin(), res.end()-1);
//	cout << hand << "->" << res << endl;
	res.push_back(tail);
	return res;
}

map<vector<int>, ll> memo;
ll enumerate(vi &hand, int tail){
	if(count(ALL(hand), tail) > M) return 0;
	
	auto state = compress(hand, tail);
	auto memop = memo.find(state);
	if(memop != memo.end()) return memop->second;
	
	int need = check(hand, seqs);
//	cout << hand << ": " << need << endl;
	if(need == 0){
		map<int, int> dist;
		FOR(it, hand) dist[*it] ++;
		ll res = 1;
		FOR(it, dist) res *= C[M][it->second];
		ll rest = L - hand.size();
		ll allr = M*(N-tail);
		if(rest){
			hand.push_back(tail);
			res = res * C[allr][rest] + enumerate(hand, tail);
			hand.pop_back();
		}
//		cout << hand << ": " << res << endl;
		return memo[state] = res;
	}else if(need > L - hand.size()) return memo[state] = 0;
	if(hand.size() == L){
		return 0;
	}
	ll res = 0;
	hand.push_back(tail);
	for(int i=tail;i<=N;i++){
		hand.back() = i;
		res += enumerate(hand, i);
	}
	hand.pop_back();
	return memo[state] = res;
}


main(){
	make_C();
	ios::sync_with_stdio(false);
	while(cin >> M >> N >> L, N){
		seqs = vector<vi>(3);
		int ast=3;
		REP(i, L){
			string s;
			cin >> s;
			if(s[0] != '*'){
				int d = s.size() - 1;
				int t = s[0] - 'a';
				if(seqs[t].size() <= d) seqs[t].resize(d+1);
				seqs[t][d] ++;
			}
		}
		RREP(i, seqs.size()){
			if(accumulate(ALL(seqs[i]), 0) <= 1) seqs.erase(seqs.begin() + i);
		}
//		cout << seqs << endl;
		vi hand;
//		printf("%lld / %lld\n", enumerate(hand, 1), C[N*M][L]);
		printf("%.10f\n", enumerate(hand, 1) / (double)C[N*M][L]);
		memo.clear();
	}
	return 0;
}
accuracy: 1
time_ms: 4630
memory_kb: 12604
final_rank: 20