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

#define pb push_back
#define mp make_pair
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef complex<double> point;
#define xx real()
#define yy imag()

#define REP(i, a, b) for(int i = (a); i < (int)(b); i++)
#define REPN(i, a, b) for(int i = (a); i <= (int)(b); i++)
#define FA(it, x) for(__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define SZ(x) (int)(x).size()
#define BE(x) (x).begin(), (x).end()
#define SORT(x) sort(BE(x))
#define _1 first
#define _2 second

#define x1 gray_cat_x1
#define y1 gray_cat_y1

template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

#define file "I1"

const double EPS = 1e-9;
const double PI = acos(-1.);
const int INF = 1e9;
const ll MOD = 998244353;

const int MAXN = 1e5 + 5, MAXSZ = 9;

map<pii, int> st;
map<pii, int> st2;

ll dp[2][1 << MAXSZ];

ll pow_mod(ll a, ll st) {
	ll ans = 1ll;
	for(; st; st /= 2ll){
		if (st & 1) {
			ans = (ans * a) % MOD;
		}
		a = (a * a) % MOD;
	}
	return ans;
}

int masks[1 << MAXSZ];
int top_masks;

int from_masks[1 << MAXSZ][1 << MAXSZ];
int top_from_masks[1 << MAXSZ];

//vi masks;
//vi from_masks[1 << MAXSZ];
int bits[MAXSZ];

int get_bit(int mask, int ind) {
	return (mask >> ind) & 1;
}

void gen_masks() {
	REP(i, 0, 1 << MAXSZ) {
		REP(j, 0, MAXSZ) {
			bits[j] = get_bit(i, j);
		}
		bool bad = false;
		if ((bits[0] ^ bits[1] ^ bits[3] ^ bits[4]) == 1) {
			bad = true;
		}
		if ((bits[4] ^ bits[5] ^ bits[7] ^ bits[8]) == 1) {
			bad = true;
		}
		if ((bits[2] ^ bits[4] ^ bits[6]) == 1) {
			bad = true;
		}
		if (!bad) {
			masks[top_masks++] = i;
			//printf("%d\n", i);
		}
	}
	
	REP(i, 0, top_masks) {
		REP(j, 0, top_masks) {
			int bad = false;
			REPN(k, 4, 8) {
				if (k == 6) {
					continue;
				}
				if (get_bit(masks[i], k) != get_bit(masks[j], k - 4)) {
					bad = true;
				}
			}
			if (!bad) {
				from_masks[masks[i]][top_from_masks[masks[i]]++] = masks[j];
			}
		}
	}
}

bool check_mask(int s, int mask) {
	for(int i = 0; i < 3; i++) {
		for(int j = 0; j < 3; j++) {
			int bit_ind = 3 * i + j;
			int ii = s + 2 - i;
			int jj = s + 2 - j;			
			if (st.find(mp(ii, jj)) != st.end() && st[mp(ii, jj)] != get_bit(mask, bit_ind)) {
				return false;
			}
		}
	}
	return true;
}

void solve(){
	int n, m;
	scanf("%d%d", &n, &m);
	REP(i, 0, m) {
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		if (abs(a - b) > 2) {
			if (st2.find(mp(b, a)) != st2.end()) {
				if (st2[mp(b, a)] != c) {
					printf("0\n");
					return;
				}
			} else {
				st2[mp(a, b)] = c;
			}
		} else {
			st[mp(a, b)] = c;
		}
	}
	
	if (n == 2) {
		n = 3;
		st[mp(1, 3)] = 0;
		st[mp(2, 3)] = 0;
		st[mp(3, 3)] = 0;
		st[mp(3, 2)] = 0;
		st[mp(3, 1)] = 0;
		ll ans = 0ll;
		REP(i, 0, 1 << MAXSZ) {
			if (check_mask(1, i)) {
				if (get_bit(i, 8) ^ get_bit(i, 7) ^ get_bit(i, 5) ^ get_bit(i, 4) == 0) {
					ans++;
				}
			}
		}
		cout << ans << endl;
		return;
	}
	
	gen_masks();
	
	REP(i, 0, top_masks) {
		if (check_mask(1, masks[i])) {
			/*REP(k, 0, MAXSZ) {
				printf("%d", (masks[i] >> k) & 1);
			}
			putchar('\n');*/
			dp[1][masks[i]] = 1;
		}
	}
	
	REPN(i, 2, n - 2) {
		int ind = i & 1;
		REP(j, 0, top_masks) {
			int cur_mask = masks[j];
			dp[ind][cur_mask] = 0;
			if (!check_mask(i, cur_mask)) {
				continue;
			}
			REP(k, 0, top_from_masks[cur_mask]) {
				int last_mask = from_masks[cur_mask][k];
				dp[ind][cur_mask] = (dp[ind][cur_mask] + dp[ind ^ 1][last_mask]) % MOD;
			}
		}
	}
	
	ll ans = 0ll;
	REP(j, 0, top_masks) {
		ans = (ans + dp[n & 1][masks[j]]) % MOD;
	}
	//cout << ans << endl;
	
	if (n > 3) {
		ll mul = ((ll)n - 2) * ((ll)n - 3) / 2 - SZ(st2);
		mul = pow_mod(2ll, mul);
		ans = (ans * mul) % MOD;
	}
	cout << ans << endl;
}   

int main(){

    //freopen(file".in", "r", stdin); freopen(file".out", "w", stdout);
    int t = 1;
    //cin >> t;
    while(t--){
        solve();    
    }
}


Measured memory_bytes: 5632