#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class A> ostream& operator<<(ostream &cout, vector<A> const &v) {cout << "["; for(int i = 0; i < (int)v.size(); i++) {if (i) cout << ", "; cout << v[i];} return cout << "]";};
template<class A, class B> ostream& operator<<(ostream &cout, const pair<A,B> &x) {return cout << "(" <<x.first << ", " << x.second << ")";};
template<class T> void pv(T a, T b) {cerr << "["; for (T i = a; i != b; ++i) {if (i != a) cerr << ", "; cerr << *i;}cerr << "]\n";}
void _print() {cerr << "]\n";}
template<class T, class... V> void _print(T t, V... v) {cerr << t; if (sizeof...(v)) cerr << ", "; _print(v...);}
#define debug(x...) cerr << "[" << #x << "] = [", _print(x)
#define fi first
#define se second
#define SZ(x) (int)((x).size())
#define pii pair<int,int>
#define uid(x,y) uniform_int_distribution<int>(x,y)(rng)
vector<array<int,2>> qu[25];
vector<int> msk[25];
ll dp[25][1<<20];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,m;
    cin >> n >> m;
    for (int q = 0; q < m; q++) {
        int x,y,z;
        cin >> x >> y >> z;
        y--;
        qu[x].push_back({y,z});
    }
    for (int q = 1; q < (1<<20); q++) msk[__builtin_popcount(q)].push_back(q);
    dp[0][0] = 1;
    for (int q = 1; q <= n; q++) {
        for (int w : msk[q]) {
            bool ok = true;
            for (array<int,2> a : qu[q]) {
                int y = (1<<(a[0]+1))-1;
                if (__builtin_popcount(y&w) > a[1]) ok = false;
            }
            if (ok) {
                for (int e = 0; e < n; e++) {
                    if ((w>>e)&1) dp[q][w] += dp[q-1][w^(1<<e)];
                }
            }
        }
    }
    cout << dp[n][(1<<n)-1] << '\n';
    return 0;
}



#include<fstream>
#include<iostream>
#include<sstream>
#include<vector>
#include<stack>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<tuple>
#include<iomanip>
#include<bitset>
#include<stdio.h>
#include<set>
#include<array>
using namespace std;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
using graph = vector<vector<long long>>;
const long long MOD = 1000000007;
const long long INF = 1e18;
using ll = long long;
using P = pair<int,int>;

void chmin(int &x,int y){ x = min(x,y); }

int digit(ll x){
  int count = 1;
  while(x/10>0){
    count ++;
    x /= 10;
  }
  return count;
}

bool prime(ll x){
  if(x==1) return false;
  for(ll i=2;i*i<=x;i++){
    if(x%i==0) return false;
  }
  return true;
}

void decom(ll x,map<ll,int> &hatano){
  for(ll i=2;i*i<=x;i++){
    if(x%i==0&&prime(i)){
      while(x%i==0){
      x /= i;
      hatano[i] ++;
    }
    }
  }
  if(x!=1) hatano[x] ++;
}

ll speedpow(ll x,ll y){
  ll res = 1;
  ll test = x;
  for(int i=0;i<31;i++){
    if(y&(1<<i)) res *= test;
    res = res%MOD;
    test = (test*test)%MOD;
  }
  return res;
}

ll combination(ll x,ll y){
  ll test = 1;
  ll test1 = 1;
  for(ll i=0;i<y;i++){
    test = (test*(x-i))%MOD;
    test1 = (test1*(i+1LL))%MOD;
  }
  return (test * speedpow(test1,MOD-2))%MOD ;
}

int euclid(int x,int y){
  if(y==0) return x;
  return euclid(y,x%y);
}


int main(){
    int n,m;cin >> n >> m;
    int x[m],y[m],z[m];
    rep(i,m) cin >> x[i] >> y[i] >> z[i];

    ll k = (1LL<<n);

    vector<ll> dp(k,0);

    dp[0] = 1;

    for(ll bit=0;bit<k;bit++){
      rep(j,n){
        if(bit&(1LL<<j)) continue;
        bool ara = true;
        ll test = (bit|(1LL<<j));
        rep(l,m){
            int p = __builtin_popcount(test);
            if(x[l]!=p) continue;
            int count = 0;
            rep(m,n){
              if((test&(1LL<<m))&&(m+1<=y[l])) count ++;
            //  if(j+1<=y[l]) count ++;
            }
            if(count>z[l]) ara = false;
          //  cout << p << " " << x[l] << " " << bit <<endl;
        }
        if(ara) dp[bit|(1LL<<j)] += dp[bit];

      }
    }

//cout << pow(2,18)*18*100 << endl;
cout << dp[k-1] << endl;

}
