#include <stdio.h>
#include <vector>
#include <algorithm>

using namespace std;

struct condition {
    int x,y,z;
};
bool cmp(condition& a, condition& b) {
    return a.x < b.x;
}

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    vector<condition> con(m);
    for (int i=0; i<m; ++i)
        scanf("%d%d%d", &con[i].x, &con[i].y, &con[i].z);
    sort(con.begin(), con.end(), cmp);
    vector<vector<long long>> dp(n+1, vector<long long>(1<<n, 0));
    dp[0][0] = 1;
    int tmp_con = 0;
    for (int i=1; i<=n; ++i) {
        for (int j=0; j<(1<<n); ++j) {
            int num_1 = 0; int tmp = j;
            while (tmp) {if (tmp%2) num_1++; tmp/=2;}
            if (num_1 != i) continue;
            for (int k=0; k<n; ++k) {
                if ( (j & (1<<k)) > 0) {
                    dp[i][j] += dp[i-1][j-(1<<k)];
                }
            }
            //printf("%d %d %lld\n", i, j, dp[i][j]);
        }
        while (tmp_con<con.size() && con[tmp_con].x == i) {
            for (int j=0; j<(1<<n); ++j) {
                int num_1 = 0;
                for (int k=0; k<con[tmp_con].y; ++k) {
                    if ( (j & (1<<k)) > 0) num_1++;
                }
                if (num_1 > con[tmp_con].z) dp[i][j] = 0;
            }
            tmp_con++;
        }
    }
    printf("%lld\n", dp[n][(1<<n) -1]);
}
/*** author: yuji9511 ***/
#include <bits/stdc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using ll = long long;
using lpair = pair<ll, ll>;
using vll = vector<ll>;
const ll MOD = 1e9+7;
const ll INF = 1e18;
#define rep(i,m,n) for(ll i=(m);i<(n);i++)
#define rrep(i,m,n) for(ll i=(m);i>=(n);i--)
ostream& operator<<(ostream& os, lpair& h){ os << "(" << h.first << ", " << h.second << ")"; return os;}
#define printa(x,n) for(ll i=0;i<n;i++){cout<<(x[i])<<" \n"[i==n-1];};
void print() {}
template <class H,class... T>
void print(H&& h, T&&... t){cout<<h<<" \n"[sizeof...(t)==0];print(forward<T>(t)...);}
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 (b<a) { a=b; return 1; } return 0; }

void solve(){
    ll N,M;
    cin >> N >> M;
    vll X(M), Y(M), Z(M);
    rep(i,0,M) cin >> X[i] >> Y[i] >> Z[i];
    rep(i,0,M) X[i]--;
    vector<vll> dp(N+1, vll(1LL<<N, 0));
    dp[0][0] = 1;
    typedef struct {ll x,y,z; } P;
    vector<vector<P> > alt(N);
    rep(i,0,M){
        alt[X[i]].push_back({X[i], Y[i], Z[i]});
    }

    
    rep(i,0,N){
        rep(bit,0,1LL<<N){
            if(dp[i][bit] == 0) continue;
            rep(j,0,N){ //j: 追加する数
                if(bit & (1LL<<j)) continue;
                vll sum(N+1, 0);
                ll newbit = (bit | (1LL<<j));
                rep(k,0,N){
                    if(newbit & (1LL<<k)){
                        sum[k+1] = sum[k] + 1;
                    }else{
                        sum[k+1] = sum[k];
                    }
                }
                bool ok = true;
                for(auto &e: alt[i]){
                    if(sum[e.y] > e.z) ok = false;
                }
                if(ok){
                    dp[i+1][newbit] += dp[i][bit];
                }
            }
        }
    }
    ll ans = dp[N][(1LL<<N)-1];
    print(ans);
    

}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    solve();
}