// Template
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <iomanip>
#include <tuple>
#include <utility>
#include <queue>
#include <set>
#include <map>
#define rep_override(x, y, z, name, ...) name
#define rep2(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep3(i, l, r) for (int i = (int)(l); i < (int)(r); ++i)
#define rep(...) rep_override(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define all(x) (x).begin(), (x).end()
using namespace std;
using ll = long long;
constexpr int inf = 1001001001;
constexpr ll infll = 3003003003003003003LL;
template <typename T>
inline bool chmin(T &x, const T &y) {
    if (x > y) {
        x = y;
        return true;
    }
    return false;
}
template <typename T> 
inline bool chmax(T &x, const T &y) {
    if (x < y) {
        x = y;
        return true;
    }
    return false;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &vec) {
    for (T &element : vec) is >> element;
    return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &vec) {
    for (int i = 0, vec_len = (int)vec.size(); i < vec_len; ++i) {
        os << vec[i] << (i + 1 == vec_len ? "" : " ");
    }
    return os;
}
struct IOSET {
    IOSET() {
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(10);
    }
} ioset;

// Main
int main() {
    int n, m;
    cin >> n >> m;
    vector<int> x(m), y(m), z(m);
    rep(i, m) cin >> x[i] >> y[i] >> z[i];
    
    vector<vector<int>> idx(n + 1);
    rep(i, m) idx[x[i]].push_back(i);
    
    vector<ll> dp(1 << n, 0);
    dp[0] = 1;
    rep(i, 1, 1 << n) {
        bool ok = true;
        for (int j : idx[__builtin_popcount(i)]) {
            int cnt = __builtin_popcount(i & ((1 << y[j]) - 1));
            if (cnt > z[j]) ok = false;
        }
        if (ok) {
            rep(j, n) {
                if (i & (1 << j)) {
                    dp[i] += dp[i ^ (1 << j)];
                }
            }
        }
    }
    
    cout << dp[(1 << n) - 1] << "\n";
}
#include <bits/stdc++.h>

int main(){
    int N, M;
    std::cin >> N >> M;
    
    std::vector< std::pair< int, std::pair< int, int > > > XYZ(M);
    for(int i=0; i<M; i++){
        std::cin >> XYZ[i].first >> XYZ[i].second.first >> XYZ[i].second.second;
        //XYZ[i].first--;
        XYZ[i].second.first--;
    }
    
    std::sort(XYZ.begin(), XYZ.end());
    
    std::vector< std::vector< int > > Y(N+1);
    std::vector< std::vector< int > > Z(N+1);
    for(int i=0; i<M; i++){
        Y[XYZ[i].first].push_back(XYZ[i].second.first);
        Z[XYZ[i].first].push_back(XYZ[i].second.second);
    }
    
    int pat = 1 << N;
    std::vector< std::vector< long long > > num(N+1, std::vector< long long >(pat, 0));
    for(int i=0; i<N; i++){
        num[i+1] = num[i];
        for(int j=0; j<pat; j++){
            int mask = 1 << i;
            if(j & mask){
                num[i+1][j]++;
            }
        }
    }
    
    std::vector< long long > DP(pat, 0);
    std::vector< long long > DPnum(pat, 0);
    DP[0] = 1;
    for(int i=0; i<pat; i++){
        for(int j=0; j<Y[DPnum[i]].size(); j++){
            if(num[Y[DPnum[i]][j]+1][i] > Z[DPnum[i]][j]){
                DP[i] = 0;
            }
        }
        for(int k=0; k<N; k++){
            int mask = 1 << k;
            if((i & mask) == 0){
                DP[i | mask] += DP[i];
                DPnum[i | mask]++;
            }
        }
    }
    
    //for(int i=0; i<pat; i++){
    //    std::cout << DP[i] << " ";
    //}
    //std::cout << std::endl;
    
    
    std::cout << DP[pat-1] << std::endl;
    
    return 0;
}

