#include <bits/stdc++.h>
#define REP(i, n) for (int64_t i = 0; (i) < (int64_t)(n); ++(i))
#define REP3(i, m, n) for (int64_t i = (m); (i) < (int64_t)(n); ++(i))
#define REP_R(i, n) for (int64_t i = (int64_t)(n)-1; (i) >= 0; --(i))
#define REP3R(i, m, n) for (int64_t i = (int64_t)(n)-1; (i) >= (int64_t)(m); --(i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;

int64_t solve(int64_t N, int64_t M, const vector<int64_t>& X, const vector<int64_t>& Y, const vector<int64_t>& Z) {
    vector<int64_t> dp(1<<N, 0);
    dp[0] = 1;
    REP(bit, 1<<N){
        int64_t m = __builtin_popcountll(bit);
        REP(dst, N){
            if((bit>>dst)&1) continue;
            vector<int64_t> cnt(N, 0);
            REP(i, N){
                if((bit>>i)&1) cnt[i] += 1;
            }
            cnt[dst] += 1;
            REP(i, N-1){
                cnt[i+1] += cnt[i];
            }
            bool flag = true;
            REP(i, M){
                if(X[i] < m) continue;
                if(cnt[Y[i]] > Z[i]){
                    flag = false;
                    break;
                }
            }
            if(flag){
                dp[bit|1<<dst] += dp[bit];
            }
        }
    }
    return dp[(1<<N)-1];
    // TODO: edit here
}

// generated by online-judge-template-generator v4.7.1 (https://github.com/online-judge-tools/template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    int64_t N, M;
    cin >> N >> M;
    vector<int64_t> X(M), Y(M), Z(M);
    REP (i, M) { cin >> X[i] >> Y[i] >> Z[i]; X[i]--; Y[i]--; }
    int64_t ans = solve(N, M, X, Y, Z);
    cout << ans << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int N, M;
    cin >> N >> M;
    vector<vector<array<int, 2>>> A(N + 1);
    for (int i = 0; i < M; i++) {
        int X, Y, Z;
        cin >> X >> Y >> Z;
        A[X].push_back({Y, Z});
    }
    vector<int64_t> dp(1<<N);
    dp[0] = 1;
    for (int i = 0; i < (1 << N); i++) {
        int n = __builtin_popcount(i);
        int valid = 1;
        for (auto u : A[n]) {
            int m = __builtin_popcount(i & ((1 << u[0]) - 1));
            if (m > u[1]) {
                valid = 0;
                break;
            }
        }
        if (valid) {
            for (int j = 0; j < N; j++) {
                if ((i & (1 << j)) == 0) continue;
                dp[i] += dp[i^(1<<j)];
            }
        }
    }
    cout << dp[(1<<N) - 1];
}