#include<bits/stdc++.h>
// #define int long long
#define mod 998244353
#define inf 0x3f3f3f3f3f3f3f3f
#define meow(args...) fprintf(stderr,args)
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,U,ans;
int a[20][20];
int f[50010][1024],g[1024][20];
inline void md(int &x){x=(x>=mod)?x-mod:x;}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	n=read(),m=read();U=(1<<10)-1;
	for(int i=1,x,y;i<=m;i++){x=read(),y=read();a[x][y]=a[y][x]=1;}
	for(int sta=0;sta<=U;sta++) for(int i=0;i<=9;i++){
		for(int v=0;v<i&&~g[sta][i];v++) if((sta>>v&1)&&a[v][i]) g[sta][i]=-1;
		if(~g[sta][i]){
			g[sta][i]=sta|(1<<i);
			for(int v=0;v<=9;v++) if(i!=v&&(sta>>v&1)&&!a[i][v]) g[sta][i]^=1<<v;
		}
	}
	f[0][0]=1;
	for(int i=1;i<=n;i++) for(int sta=0;sta<=U;sta++) if(f[i-1][sta]){
		for(int v=0;v<=9;v++) if(~g[sta][v]) md(f[i][g[sta][v]]+=f[i-1][sta]);
	}
	for(int sta=0;sta<=U;sta++) md(ans+=f[n][sta]);
	printf("%d\n",ans);
	return 0;
}

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

// https://codeforces.com/contest/1679/submission/157178900
const int MOD = 998244353;
const int K = 10;
int dp[1<<K], ndp[1<<K];
int mask[K];
// dp[mask] = # of lexicographically minimal representatives where mask
// represents banned digits

int main () {
  ios_base::sync_with_stdio(0); cin.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    mask[u] |= 1<<v;
    mask[v] |= 1<<u;
  }
  dp[0] = 1;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (1<<K); j++) {
      if (dp[j]) {
        for (int k = 0; k < K; k++) {
          if (!((j>>k)&1)) {
            // 2^k-1: digits smaller than k
            // mask[k]: can be moved past k
            int z = (j|((1<<k)-1))&mask[k];
            ndp[z] = (ndp[z]+dp[j]) % MOD;
          }
        }
      }
    }
    swap(dp, ndp);
    fill(ndp, ndp+(1<<K), 0);
  }
  cout << accumulate(dp, dp+(1<<K), 0LL)%MOD << '\n';
}

#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
typedef pair<int,int> pii;
#define fi first
#define se second
#define SZ(x) ((int)((x).size()))
#define uid(x,y) uniform_int_distribution<int>(x,y)(rng)
template<class T, class V> void ckmin(T& x, V y) {if (x > y) x = y;}
template<class T, class V> void ckmax(T& x, V y) {if (x < y) x = y;}
template<class T> void pv(T a, T b) {for (T i = a; i != b; i++) cerr << *i << ' '; cerr << '\n';}
void dbg() {cerr << '\n';}
template<class T, class... V> void dbg(T t, V... v) {cerr << t << ' '; dbg(v...);}
template<int modd> struct modint {
    static const int mod = modd;
    int v; explicit operator int() const { return v;}
    modint() : v(0) {}
    modint(ll x) : v(int(x%mod)) {if (v < 0) v += mod;}
    friend bool operator==(const modint& a, const modint& b) {return a.v == b.v;}
    friend bool operator!=(const modint& a, const modint& b) {return a.v != b.v;}
    friend bool operator<(const modint& a, const modint& b) {return a.v < b.v;}
    modint& operator+=(const modint& a) {if ((v += a.v) >= mod) v -= mod; return *this;}
    modint& operator-=(const modint& a) {if ((v -= a.v) < 0) v += mod; return *this;}
    modint& operator*=(const modint& a) {v = int((ll)v*a.v%mod); return *this;}
    modint& operator/=(const modint& a) {return (*this) *= inv(a);}
    friend modint qpow(modint a, ll p) {modint ret = 1; for (; p; p /= 2, a *= a){if (p&1) ret *= a;} return ret;}
    friend modint inv(const modint& a) {return qpow(a,mod-2);}
    modint operator-() const {return modint(-v);}
    modint& operator++() {return *this += 1;}
    modint& operator--() {return *this -= 1;}
    friend modint operator+(modint a, const modint& b) {return a += b;}
    friend modint operator-(modint a, const modint& b) {return a -= b;}
    friend modint operator*(modint a, const modint& b) {return a *= b;}
    friend modint operator/(modint a, const modint& b) {return a /= b;}
    friend ostream& operator<<(ostream& out, modint a) {return out << a.v;}
    friend istream& operator>>(istream& in, modint& a) {ll b; in >> b; a.v = b%mod; return in;}
};
using mint = modint<998244353>;
int adj[10][10], nxt[1024][10];
mint dp[50005][1024];
void solve() {
    int n,m;
    cin >> n >> m;
    for (int q = 0; q < m; q++) {
        int a,b;
        cin >> a >> b;
        adj[a][b] = 1;
        adj[b][a] = 1;
    }
    for (int q = 0; q < 1024; q++) {
        for (int w = 0; w < 10; w++) {
            bool ok = true;
            for (int e = w+1; e < 10; e++) {
                if ((q>>e)&1) {
                    if (adj[w][e]) {
                        ok = false;
                    }
                }
            }
            if (!ok) {
                nxt[q][w] = -1;
                continue;
            }
            int ret = q;
            for (int e = 0; e < 10; e++) {
                if ((q>>e)&1) {
                    if (!adj[w][e]) ret ^= (1<<e);
                }
            }
            ret |= (1<<w);
            nxt[q][w] = ret;
        }
    }
    dp[0][0] = 1;
    for (int q = 1; q <= n; q++) {
        for (int w = 0; w < 1024; w++) {
            for (int e = 0; e < 10; e++) {
                if (nxt[w][e] == -1) continue;
                dp[q][nxt[w][e]] += dp[q-1][w];
            }
        }
    }
    mint ans = 0;
    for (int q = 0; q < 1024; q++) ans += dp[n][q];
    cout << ans << '\n';
}
int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--) solve();
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long llo;
#define a first
#define b second
#define pb push_back
#define endl '\n'
const llo mod=998244353;

llo n,m;
llo vis[10][10];
llo ss[10];
llo dp[2][1<<10];
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cin>>n;
	cin>>m;
	for(llo i=0;i<m;i++){
		llo aa,bb;
		cin>>aa>>bb;
		vis[aa][bb]=1;
		vis[bb][aa]=1;
		ss[aa]^=(1<<bb);
		ss[bb]^=(1<<aa);
	}
	vector<pair<llo,llo>> aa;
	for(llo i=0;i<(1<<10);i++){
		for(llo j=0;j<10;j++){
			if((ss[j]&i)&((1<<(j))-1)){
				continue;
			}

			llo xx=(ss[j]&i)|(1<<j);
			aa.pb({xx,i});
		}
	}
	for(llo i=0;i<10;i++){
		dp[0][1<<i]=1;
	}
	for(llo j=1;j<n;j++){

		for(auto i:aa){
			dp[1][i.a]+=dp[0][i.b];
			if(dp[1][i.a]>=mod){
				dp[1][i.a]-=mod;
			}
		}
		for(llo i=0;i<(1<<10);i++){
			dp[0][i]=dp[1][i];
			dp[1][i]=0;
		}
	}
	llo ans=0;
	for(llo i=0;i<(1<<10);i++){
		ans=(ans+dp[0][i]);
	}
	ans%=mod;
	cout<<ans<<endl;

	return 0;
}

#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;

const int P = 998244353;

inline void add(int &a, const int &b) { a += b; a = (a >= P ? a - P : a); }
inline int aad(const int &a, const int &b) { return (a + b >= P ? a + b - P : a + b); }
inline void mul(int &a, const int &b) { a = 1ll * a * b % P; }
inline int mut(const int &a, const int &b) { return 1ll * a * b % P; }

const int NR = 5e4 + 10;

int n, m;
int ans = 0;
int to[1 << 10][10], f[NR][1 << 10];
bool v[10][10];

int main()
{
#ifdef WYZ
	freopen("1.in", "r", stdin);
	freopen("1.out", "w", stdout);
#endif
	ios::sync_with_stdio(0);

	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int x, y;
		cin >> x >> y;
		v[x][y] = v[y][x] = 1;
	}

	for (int S = 0; S < (1 << 10); S++)
		for (int c = 0; c < 10; c++) {
			bool flag = 1;
			for (int t = 0; t < c; t++)
				if ((S & (1 << t)) && v[c][t]) { flag = 0; break; }
			if (!flag) to[S][c] = -1;
			else {
				to[S][c] = (1 << c);
				for (int t = 0; t < 10; t++)
					if ((S & (1 << t)) && v[c][t]) to[S][c] |= (1 << t);
			}
		}

	f[0][0] = 1;
	for (int i = 0; i < n; i++)
		for (int S = 0; S < (1 << 10); S++) {
			if (!f[i][S]) continue;
			for (int c = 0; c < 10; c++)
				if (to[S][c] != -1) add(f[i + 1][to[S][c]], f[i][S]);
		}

	for (int i = 0; i < (1 << 10); i++) add(ans, f[n][i]);
	cout << ans << '\n';

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long  ll;
typedef pair<int,int>  ii;

#define ff   first
#define ss   second

const int mod = 998244353;
const int N = 50002;

int dp[N][(1<<10)];
int sw[12][12];
int bloq[12];
int add[12];
int n,m;

int go (int i, int msk) {
  if (i == n) return 1;
  auto &rf = dp[i][msk];
  if (rf!=-1)return rf;
  rf = 0;
  for (int nxt = 0; nxt < 10; ++nxt) {
    if (msk&(1<<nxt))continue;
    rf = (rf + go(i+1, ((msk & bloq[nxt])|add[nxt]))) % mod;
  }
  return rf;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);cout.tie(0);
  #ifdef LOCAL
  freopen("input.txt","r",stdin);
  #endif // LOCAL
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int u, v; cin >> u >> v;
    sw[u][v]=1;
    sw[v][u]=1;
  }
  memset(dp,-1,sizeof dp);
  for (int i = 0; i < 10; ++i) {
    for (int j = 0; j < i; ++j) {
      if (sw[i][j]) add[i] |= (1<<j);
    }
    for (int j = 0; j < 10; ++j) {
      if (sw[i][j]) bloq[i] |= (1<<j);
    }
  }
  cout << go(0,0) << '\n';
}

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

const int maxn = 10;
const int mod = 998244353;

int vis[maxn][maxn],tran[maxn][1<<maxn];
int dp[2][1<<maxn];

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;++i){
		int u,v;
		scanf("%d%d",&u,&v);
		vis[u][v]=vis[v][u]=1;
	}
	for(int i=0;i<maxn;++i){
		for(int j=0;j<(1<<maxn);++j){
			bool ok=true;
			for(int k=0;k<maxn;++k){
				if(!((j>>k)&1) || !vis[k][i])continue;
				if(k<i){
					ok=false;
					break;
				}else{
					tran[i][j]|=1<<k;
				}
			}
			if(!ok)tran[i][j]=-1;else{
				tran[i][j]|=1<<i;
			}
		}
	}
	dp[0][0]=1;
	for(int i=1;i<=n;++i){
		int o=!(i&1);
		for(int j=0;j<(1<<maxn);++j){
			for(int k=0;k<maxn;++k){
				if(tran[k][j]==-1)continue;
				dp[i&1][tran[k][j]]+=dp[o][j];
				(dp[i&1][tran[k][j]]>=mod && (dp[i&1][tran[k][j]]-=mod));
			}
		}
		for(int j=(1<<maxn)-1;j>=0;--j){
			dp[o][j]=0;
		}
	}
	int ans=0;
	for(int i=0;i<(1<<maxn);++i){
		ans+=dp[n&1][i];
		(ans>=mod && (ans-=mod));
	}
	printf("%d\n",ans);
}

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<bitset>
#include<random>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>

#define fi first
#define se second
#define max Max
#define min Min
#define abs Abs
#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
#define pb(x) push_back(x)
#define lowbit(x) ((x)&(-(x)))
#define fan(x) ((((x)-1)^1)+1)
#define mp(x,y) make_pair(x,y)
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define INF 0x3f3f3f3f

using namespace std;

inline int read()
{
	int ans=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){ans=(ans<<1)+(ans<<3)+c-'0';c=getchar();}
	return ans*f;
}

inline void write(int x)
{
	if(x<0) putchar('-'),x=-x;
	if(x/10) write(x/10);
	putchar((char)(x%10)+'0');
}

template<typename T>inline T Abs(T a){return a>0?a:-a;};
template<typename T,typename TT>inline T Min(T a,TT b){return a<b?a:b;}
template<typename T,typename TT> inline T Max(T a,TT b){return a<b?b:a;}

const int N=5e4+5,mod=998244353;
int n,m,w[10][10],w2[10],dp[N][1024],to[1024][10];

signed main()
{
	n=read();m=read();
	for(int i=1;i<=m;++i)
	{
		int u=read(),v=read();
		if(u>v) swap(u,v);
		w[u][v]=w[v][u]=1;
		w2[v]|=(1<<u);
	}
	for(int i=0;i<1024;++i)
		for(int j=0;j<10;++j)
		{
			int ne=(1<<j);
			for(int k=0;k<10;++k)
				if(((i>>k)&1)&&w[k][j])
					ne|=(1<<k);
			to[i][j]=ne;
		}
	dp[0][0]=1;
	for(int i=0;i<n;++i)
		for(int j=0;j<1024;++j)
			if(dp[i][j])
			{
				int msk=0;
				for(int k=0;k<10;++k)
					if((j>>k)&1)
						msk|=w2[k];
				for(int k=0;k<10;++k)
					if(!((msk>>k)&1))
						dp[i+1][to[j][k]]=(dp[i+1][to[j][k]]+dp[i][j])%mod;
			}
	int ans=0;
	for(int i=0;i<1024;++i)
		ans=(ans+dp[n][i])%mod;
	write(ans);
	return 0;
}

#pragma GCC target("avx")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")

#include <bits/stdc++.h>
#define between(x, l, r) (x >= l && x <= r)
#define point(a, b, m) ((a - 1) * m + b)
#define IDX(x, m) \
    (PII) { (x - 1) / m + 1, (x - 1) % m + 1 }
#define all(x) (x).begin(), (x).end()
#define np next_permutation
#define lb lower_bound
#define ub upper_bound
#define eb emplace_back
#define pb push_back
#define y second
#define x first

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x; }

constexpr int N = 5e5 + 10, M = 4 * N, mod = 998244353;
constexpr LL INF = 1e15;

// int/LL 的ksm别使用该函数, 此函数不带自动取模
template <class T>
inline T Norm(const T &v) { return (v % mod + mod) % mod; }
template <class T>
constexpr T ksm(T a, int b, const int &p = mod, T c = 1)
{
    for (a %= p; b; a *= a, b >>= 1)
        if (b & 1)
            c *= a;
    return c;
}

struct Z
{
    using F = long long;
    F v;
    Z(long long _x = 0) : v(Norm(_x)) {}
    // C++20 可用
    // auto operator<=>(const Z &) const = default;
    Z operator-() const { return Z(Norm(mod - v)); }
    Z inv() const { return ksm(*this, mod - 2, mod); }
    Z &operator*=(const Z &R) { return v = v * R.v % mod, *this; }
    Z &operator+=(const Z &R) { return v = Norm(v + R.v), *this; }
    Z &operator-=(const Z &R) { return v = Norm(v - R.v), *this; }
    Z &operator/=(const Z &R) { return *this *= R.inv(); }
    Z &operator%=(const F &R) { return v %= R, *this; }
    friend Z operator*(Z L, const Z &R) { return L *= R; }
    friend Z operator+(Z L, const Z &R) { return L += R; }
    friend Z operator-(Z L, const Z &R) { return L -= R; }
    friend Z operator/(Z L, const Z &R) { return L /= R; }
    friend Z operator%(Z L, const F &R) { return L %= R; }
    // C++ 14
    friend auto &operator>>(istream &i, Z &z) { return i >> z.v; }
    friend auto &operator<<(ostream &o, const Z &z) { return o << z.v; }
};

int e[10][10], nxt[1 << 10][10];

/*
我们把字典序最小的看作这类的代表
那么那些大的数满足
y > x

y d1 d2 d3 ... ds x

(x,ds)
(x,d_{s-1})
...
(x,d1)
(x,y)

d_i >= d_{i-1}
*/

void solve()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        e[x][y] = e[y][x] = 1;
    }

    for (int i = 0; i < (1 << 10); i ++ )
        for (int j = 0; j < 10; j ++ )
            if ((i >> j & 1) == 1) // 如果这种情况下，我最后一位为j
            {
                nxt[i][j] = i; //原本的情况
                // 如果k比我之前出现过的小, 并且可以被换到前面, 那么就去掉k, 否则那就加上k
                for (int k = 0; k < j; k ++ )
                    if (e[j][k]) nxt[i][j] &= ~(1 << k);
                    else nxt[i][j] |= 1 << k;

                // 如果k比我之前出现过的大,并且和j没有边, 那么直接加上去
                for (int k = j + 1; k < 10; k++)
                    if (!e[j][k]) nxt[i][j] |= 1 << k;
            }

    vector<Z> f(1 << 10);
    f[(1 << 10) - 1] = 1;
    for (int i = 1; i <= n; i ++ )
    {
        vector<Z> g(1 << 10);
        for (int j = 0; j < (1 << 10); j ++ )
            for (int k = 0; k < 10; k ++ )
                if(j >> k & 1) g[nxt[j][k]] += f[j];

        swap(f, g);
    }

    Z res = 0;
    for (int i = 0; i < (1 << 10); i ++ )
        res += f[i];

    cout << res << '\n';
}

int main()
{
    // freopen("C:\\AKICPC\\test.in", "r", stdin), freopen("C:\\AKICPC\\test.out", "w", stdout);
    ios::sync_with_stdio(0), cin.tie(0);
    cout.precision(2), cout.setf(ios::fixed);
    // auto now = clock();

    // int t;
    // cin >> t;
    // while (t -- )
    solve();

    // cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
    return 0;
}

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

typedef long long ll;
const int maxn = 1<<9;
const int Mod = 998244353;

int dp[maxn], tmp[maxn], G[10];

int main() {

    int n, m;
    scanf("%d%d", &n, &m);
    while(m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u] |= 1 << v;
        G[v] |= 1 << u;
    }

    dp[0] = 1;
    for(int i = 1; i <= n; i++) {
        memset(tmp, 0, sizeof(tmp));
        for(int j = 0; j < maxn; j++) if(dp[j])
            for(int k = 0; k < 10; k++)
                if(!(j&(1<<k)-1&G[k]))
                    tmp[(1<<k|j&G[k])&((1<<9)-1)] = (tmp[(1<<k|j&G[k])&((1<<9)-1)] + dp[j]) % Mod;
        memcpy(dp, tmp, sizeof(tmp));
    }

    int ans = 0;
    for(int i = 0; i < maxn; i++) ans = (ans + dp[i]) % Mod;
    printf("%d", ans);
    return 0;
}

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

typedef long long ll;
const int maxn = 1<<9;
const int Mod = 998244353;

int dp[maxn], tmp[maxn], G[10];

int main() {

    int n, m;
    scanf("%d%d", &n, &m);
    while(m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u] |= 1 << v;
        G[v] |= 1 << u;
    }

    dp[0] = 1;
    for(int i = 1; i <= n; i++) {
        memset(tmp, 0, sizeof(tmp));
        for(int j = 0; j < maxn; j++) if(dp[j])
            for(int k = 0; k < 10; k++)
                if(!(j&(1<<k)-1&G[k]))
                    tmp[(k==9?0:1)<<k|j&G[k]] = (tmp[(k==9?0:1)<<k|j&G[k]] + dp[j]) % Mod;
        memcpy(dp, tmp, sizeof(tmp));
    }

    int ans = 0;
    for(int i = 0; i < maxn; i++) ans = (ans + dp[i]) % Mod;
    printf("%d", ans);
    return 0;
}

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define PI pair<int, int>
#define PLI pair<ll, int>
#define PL pair<ll, ll>
#define MP make_pair
#define fi first
#define se second
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define random(a, b) (mtrand() % (b - a + 1) + a)
#define lc ch[x][0]
#define rc ch[x][1]
#define S(x) #x, x
#define FIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
template <class _F, class _S>
ostream& operator<<(ostream& out, const pair<_F, _S>& _pair) {
    return out << "(" << _pair.first << "," << _pair.second << ")";
}
template <class T>
ostream& operator<<(ostream& out, const vector<T>& _vec) {
    out << "[";
    for (int _vecp = 0; _vecp < _vec.size(); ++_vecp)
        out << _vec[_vecp] << ",]"[_vecp + 1 == _vec.size()];
    return out;
}
void debug() {}
template <class T, class... U>
void debug(const T& head, const U&... tail) {
    cerr << head << (sizeof...(tail) ? " " : "\n"), debug(tail...);
}
template <class... T>
void D(const T&... parm) {
    cerr << ">>> ", debug(parm...);
}
const int mx = 5e4 + 10;
ll mod = 998244353;
mt19937_64 mtrand(time(0));
int n,m,T;
int mask[11],ma[11];
int dp[2][1024]; // dp[i][j]表示前i位中状态为j的方案数，状态j表示新添加的一位不能存在在状态j中
void run_case() {
    cin>>n>>m;
    int u,v;
    for (int i=1;i<=m;++i) {
        cin>>u>>v;
        mask[v]|=1<<u;
        mask[u]|=1<<v;
        ma[u]|=1<<v;
    }
    dp[0][0]=1;
    for (int i=1;i<=n;++i) {
        int id=i&1,nid=id^1;
        memset(dp[id],0,sizeof(dp[id]));
        for (int j=0;j<1024;++j) {
            if (!dp[nid][j]) continue;
            for (int k=0,nj;k<10;++k) {
                if ((j>>k)&1) continue;
                nj=j&mask[k]|ma[k];
                dp[id][nj]+=dp[nid][j];
                if (dp[id][nj]>=mod) dp[id][nj]-=mod;
            }
        }
    }
    cout<<reduce(dp[n&1],dp[n&1]+1024,0LL)%mod<<"\n";
}
int main() {
// #define debug
#ifdef debug
    freopen("data.in", "r", stdin);
    freopen("my.out", "w", stdout);
#endif // debug
    FIO;
    T = 1;
    // cin>>T;
    for (int i = 1; i <= T; ++i) {
        run_case();
    }
}

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define PI pair<int, int>
#define PLI pair<ll, int>
#define PL pair<ll, ll>
#define MP make_pair
#define fi first
#define se second
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define random(a, b) (mtrand() % (b - a + 1) + a)
#define lc ch[x][0]
#define rc ch[x][1]
#define S(x) #x, x
#define FIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
template <class _F, class _S>
ostream& operator<<(ostream& out, const pair<_F, _S>& _pair) {
    return out << "(" << _pair.first << "," << _pair.second << ")";
}
template <class T>
ostream& operator<<(ostream& out, const vector<T>& _vec) {
    out << "[";
    for (int _vecp = 0; _vecp < _vec.size(); ++_vecp)
        out << _vec[_vecp] << ",]"[_vecp + 1 == _vec.size()];
    return out;
}
void debug() {}
template <class T, class... U>
void debug(const T& head, const U&... tail) {
    cerr << head << (sizeof...(tail) ? " " : "\n"), debug(tail...);
}
template <class... T>
void D(const T&... parm) {
    cerr << ">>> ", debug(parm...);
}
const int mx = 5e4 + 10;
ll mod = 998244353;
mt19937_64 mtrand(time(0));
int n,m,T;
int mask[1024],ma[1024];
int dp[2][1024]; // dp[i][j]表示前i位中状态为j的方案数，状态j表示新添加的一位不能存在在状态j中
void run_case() {
    cin>>n>>m;
    int u,v;
    for (int i=1;i<=m;++i) {
        cin>>u>>v;
        if (u>v) swap(u,v);
        mask[1<<v]|=1<<u;
        mask[1<<u]|=1<<v;
        ma[1<<u]|=1<<v;
    }
    dp[0][0]=1;
    for (int i=1;i<=n;++i) {
        int id=i&1,nid=id^1;
        memset(dp[id],0,1024*sizeof(dp[id][0]));
        for (int j=0;j<1024;++j) {
            if (!dp[nid][j]) continue;
            for (int k=1023-j,z,nj;k;k-=z) {
                z=k&-k,nj=j&mask[z]|ma[z];
                dp[id][nj]+=dp[nid][j];
                if (dp[id][nj]>=mod) dp[id][nj]-=mod;
            }
        }
    }
    cout<<reduce(dp[n&1],dp[n&1]+1024,0LL)%mod<<"\n";
}
int main() {
// #define debug
#ifdef debug
    freopen("data.in", "r", stdin);
    freopen("my.out", "w", stdout);
#endif // debug
    FIO;
    T = 1;
    // cin>>T;
    for (int i = 1; i <= T; ++i) {
        run_case();
    }
}

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define PI pair<int, int>
#define PLI pair<ll, int>
#define PL pair<ll, ll>
#define MP make_pair
#define fi first
#define se second
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define random(a, b) (mtrand() % (b - a + 1) + a)
#define lc ch[x][0]
#define rc ch[x][1]
#define S(x) #x, x
#define FIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
template <class _F, class _S>
ostream& operator<<(ostream& out, const pair<_F, _S>& _pair) {
    return out << "(" << _pair.first << "," << _pair.second << ")";
}
template <class T>
ostream& operator<<(ostream& out, const vector<T>& _vec) {
    out << "[";
    for (int _vecp = 0; _vecp < _vec.size(); ++_vecp)
        out << _vec[_vecp] << ",]"[_vecp + 1 == _vec.size()];
    return out;
}
void debug() {}
template <class T, class... U>
void debug(const T& head, const U&... tail) {
    cerr << head << (sizeof...(tail) ? " " : "\n"), debug(tail...);
}
template <class... T>
void D(const T&... parm) {
    cerr << ">>> ", debug(parm...);
}
const int mx = 5e4 + 10;
ll mod = 998244353;
mt19937_64 mtrand(time(0));
int n,m,T;
int mask[1024],ma[1024];
int dp[mx][1024]; // dp[i][j]表示前i位中状态为j的方案数，状态j表示新添加的一位不能存在在状态j中
void run_case() {
    cin>>n>>m;
    int u,v;
    for (int i=1;i<=m;++i) {
        cin>>u>>v;
        if (u>v) swap(u,v);
        mask[1<<v]|=1<<u;
        mask[1<<u]|=1<<v;
        ma[1<<u]|=1<<v;
    }
    dp[0][0]=1;
    for (int i=1;i<=n;++i) {
        for (int j=0;j<1024;++j) {
            if (!dp[i-1][j]) continue;
            for (int k=1023-j,z,nj;k;k-=z) {
                z=k&-k,nj=j&mask[z]|ma[z];
                dp[i][nj]+=dp[i-1][j];
                if (dp[i][nj]>=mod) dp[i][nj]-=mod;
            }
        }
    }
    cout<<reduce(dp[n],dp[n]+1024,0LL)%mod<<"\n";
}
int main() {
// #define debug
#ifdef debug
    freopen("data.in", "r", stdin);
    freopen("my.out", "w", stdout);
#endif // debug
    FIO;
    T = 1;
    // cin>>T;
    for (int i = 1; i <= T; ++i) {
        run_case();
    }
}

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

typedef long long ll;
const int maxn = 1<<9;
const int Mod = 998244353;

int dp[maxn], tmp[maxn], G[10];

int main() {

    int n, m;
    scanf("%d%d", &n, &m);
    while(m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u] |= 1 << v;
        G[v] |= 1 << u;
    }
    dp[0] = 1;
    for(int i = 1; i <= n; i++) {
        memset(tmp, 0, sizeof(tmp));
        for(int j = 0; j < maxn; j++) if(dp[j])
            for(int k = 0; k < 10; k++)
                if(!(j&((1<<k)-1)&G[k]))
                    tmp[((k==9?0:1)<<k)|(~((1<<k)-1)&j&G[k])] = (tmp[((k==9?0:1)<<k)|(~((1<<k)-1)&j&G[k])] + dp[j]) % Mod;
        memcpy(dp, tmp, sizeof(tmp));
    }

    int ans = 0;
    for(int i = 0; i < maxn; i++) ans = (ans + dp[i]) % Mod;
    cout << ans;
    return 0;
}

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

#define ll              long long
#define pb              push_back
#define all(v)          v.begin(),v.end()
#define sz(a)           (ll)a.size()
#define F               first
#define S               second
#define INF             2000000000000000000
#define popcount(x)     __builtin_popcountll(x)
#define pll             pair<ll,ll>
#define pii             pair<int,int>
#define ld              long double

template<typename T, typename U> static inline void amin(T &x, U y){ if(y < x) x = y; }
template<typename T, typename U> static inline void amax(T &x, U y){ if(x < y) x = y; }

#ifdef LOCAL
#define debug(...) debug_out(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) 3000
#endif

// const int MOD = 1000000007;
const int MOD = 998244353;

struct Mint {
    int val;

    Mint(long long v = 0) {
        if (v < 0)
            v = v % MOD + MOD;
        if (v >= MOD)
            v %= MOD;
        val = v;
    }

    static int mod_inv(int a, int m = MOD) {
        int g = m, r = a, x = 0, y = 1;
        while (r != 0) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }
        return x < 0 ? x + m : x;
    }
    explicit operator int() const {
        return val;
    }
    Mint& operator+=(const Mint &other) {
        val += other.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    Mint& operator-=(const Mint &other) {
        val -= other.val;
        if (val < 0) val += MOD;
        return *this;
    }
    static unsigned fast_mod(uint64_t x, unsigned m = MOD) {
           #if !defined(_WIN32) || defined(_WIN64)
                return x % m;
           #endif
           unsigned x_high = x >> 32, x_low = (unsigned) x;
           unsigned quot, rem;
           asm("divl %4\n"
            : "=a" (quot), "=d" (rem)
            : "d" (x_high), "a" (x_low), "r" (m));
           return rem;
    }
    Mint& operator*=(const Mint &other) {
        val = fast_mod((uint64_t) val * other.val);
        return *this;
    }
    Mint& operator/=(const Mint &other) {
        return *this *= other.inv();
    }
    friend Mint operator+(const Mint &a, const Mint &b) { return Mint(a) += b; }
    friend Mint operator-(const Mint &a, const Mint &b) { return Mint(a) -= b; }
    friend Mint operator*(const Mint &a, const Mint &b) { return Mint(a) *= b; }
    friend Mint operator/(const Mint &a, const Mint &b) { return Mint(a) /= b; }
    Mint& operator++() {
        val = val == MOD - 1 ? 0 : val + 1;
        return *this;
    }
    Mint& operator--() {
        val = val == 0 ? MOD - 1 : val - 1;
        return *this;
    }
    Mint operator++(int32_t) { Mint before = *this; ++*this; return before; }
    Mint operator--(int32_t) { Mint before = *this; --*this; return before; }
    Mint operator-() const {
        return val == 0 ? 0 : MOD - val;
    }
    bool operator==(const Mint &other) const { return val == other.val; }
    bool operator!=(const Mint &other) const { return val != other.val; }
    Mint inv() const {
        return mod_inv(val);
    }
    Mint power(long long p) const {
        assert(p >= 0);
        Mint a = *this, result = 1;
        while (p > 0) {
            if (p & 1)
                result *= a;

            a *= a;
            p >>= 1;
        }
        return result;
    }
    friend ostream& operator << (ostream &stream, const Mint &m) {
        return stream << m.val;
    }
    friend istream& operator >> (istream &stream, Mint &m) {
        return stream>>m.val;
    }
};

const int X = 10, N = 50005;
int ed[X][X];

Mint dp[N][(1 << X)];

int nxt[1 << X][X];

int _runtimeTerror_()
{
    int n, m;
    cin >> n >> m;
    while(m--) {
        int u, v;
        cin >> u >> v;
        ed[u][v] = ed[v][u] = 1;
    }

    for(int i=0;i<(1 << X);++i) {
        for(int j=0;j<10;++j) {
            nxt[i][j] = -1;
        }
    }

    for(int i=0;i<(1 << X);++i) {
        for(int j=0;j<X;++j) {
            int good = 1, msk = 0;
            for(int k=0;k<j;++k) {
                if(i & (1 << k)) {
                    if(ed[j][k]) {
                        good = 0;
                    }
                }
            }
            msk |= (1 << j);
            for(int k=j+1;k<X;++k) {
                if(i & (1 << k)) {
                    if(ed[j][k]) {
                        msk |= (1 << k);
                    }
                }
            }
            if(good) {
                nxt[i][j] = msk;
            }
        }
    }

    for(int i=0;i<10;++i) {
        dp[0][1 << i] = 1;
    }
    for(int i=1;i<n;++i) {
        for(int j=1;j<(1 << 10);++j) {
            for(int k=0;k<10;++k) {
                if(nxt[j][k] == -1) {
                    continue;
                }
                dp[i][nxt[j][k]] += dp[i - 1][j];
            }
        }
    }
    Mint ans = 0;
    for(int i=0;i<(1 << X);++i) {
        ans += dp[n-1][i];
    }
    cout << ans << "\n";
    return 0;
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    #ifdef runSieve
        sieve();
    #endif
    #ifdef NCR
        initncr();
    #endif
    int TESTS = 1;
    //cin >> TESTS;
    while(TESTS--) {
        _runtimeTerror_();
    }
    return 0;
}

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

typedef long long ll;
const int maxn = 1<<9;
const int Mod = 998244353;

int dp[maxn], tmp[maxn], G[10];

int main() {

    int n, m;
    scanf("%d%d", &n, &m);
    while(m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u] |= 1 << v;
        G[v] |= 1 << u;
    }

    dp[0] = 1;
    for(int i = 1; i <= n; i++) {
        memset(tmp, 0, sizeof(tmp));
        for(int j = 0; j < maxn; j++) if(dp[j])
            for(int k = 0; k < 10; k++)
                if(!(j&((1<<k)-1)&G[k]))
                    tmp[((k==9?0:1)<<k)|(~((1<<k)-1)&j&G[k])] = (tmp[((k==9?0:1)<<k)|(~((1<<k)-1)&j&G[k])] + dp[j]) % Mod;
        memcpy(dp, tmp, sizeof(tmp));
    }

    int ans = 0;
    for(int i = 0; i < maxn; i++) ans = (ans + dp[i]) % Mod;
    cout << ans;
    return 0;
}

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

typedef long long ll;
const int maxn = 1<<9;
const int Mod = 998244353;

int dp[maxn], tmp[maxn], G[10];

int main() {

    int n, m;
    scanf("%d%d", &n, &m);
    while(m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u] |= 1 << v;
        G[v] |= 1 << u;
    }
    dp[0] = 1;
    for(int i = 1; i <= n; i++) {
        memset(tmp, 0, sizeof(tmp));
        for(int j = 0; j < maxn; j++) if(dp[j])
            for(int k = 0; k < 10; k++)
                if(!(j&((1<<k)-1)&G[k]))
                    tmp[((k==9?0:1)<<k)|(~((1<<k)-1)&j&G[k])] = (tmp[((k==9?0:1)<<k)|(~((1<<k)-1)&j&G[k])] + dp[j]) % Mod;
        for(int j = 0; j < maxn; j++) dp[j] = tmp[j];
    }

    int ans = 0;
    for(int i = 0; i < maxn; i++) ans = (ans + dp[i]) % Mod;
    cout << ans;
    return 0;
}

#include<bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define fi first
#define se second
#define min amin
#define max amax
#define pb push_back
using namespace std;
using ll=long long;
using pii=array<int,2>;
constexpr int N=512;
constexpr int inf=1E9;
constexpr int p=998244353;
int qpow(int x,int n=p-2){int y=1;for(;n;n>>=1,x=1LL*x*x%p)if(n&1)y=1LL*y*x%p;return y;}
template<typename T=int>T read(){T x;cin>>x;return x;}
template<typename U,typename V>auto min(U x,V y){return x<y?x:y;}
template<typename U,typename V>auto max(U x,V y){return x>y?x:y;}
template<typename U,typename...V>auto min(U x,V...y){return min(x,min(y...));}
template<typename U,typename...V>auto max(U x,V...y){return max(x,max(y...));}
template<typename U,typename V>bool cmin(U &x,V y){return x>y?x=y,true:false;}
template<typename U,typename V>bool cmax(U &x,V y){return x<y?x=y,true:false;}

array<int,N>a,b;
int g[10],h[10];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(6);
    int n=read();
    for(int m=read();m--;)
    {
        int u=read(),v=read();
        g[u]|=1<<v;
        h[v]|=1<<u;
    }
    a[0]=1;
    while(n--)
    {
        for(int i=0;i<N;++i)if(a[i])
        {
            for(int j=0;j<10;++j)if(~i>>j&1)
            {
                (b[i&g[j]|h[j]]+=a[i])%=p;
            }
        }
        a=b;
        b={};
    }
    int ans=0;
    for(int i=0;i<N;++i)(ans+=a[i])%=p;
    cout<<ans<<'\n';
}

#include<bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define fi first
#define se second
#define min amin
#define max amax
#define pb push_back
using namespace std;
using ll=long long;
using pii=array<int,2>;
constexpr int N=512;
constexpr int inf=1E9;
constexpr int p=998244353;
int qpow(int x,int n=p-2){int y=1;for(;n;n>>=1,x=1LL*x*x%p)if(n&1)y=1LL*y*x%p;return y;}
template<typename T=int>T read(){T x;cin>>x;return x;}
template<typename U,typename V>auto min(U x,V y){return x<y?x:y;}
template<typename U,typename V>auto max(U x,V y){return x>y?x:y;}
template<typename U,typename...V>auto min(U x,V...y){return min(x,min(y...));}
template<typename U,typename...V>auto max(U x,V...y){return max(x,max(y...));}
template<typename U,typename V>bool cmin(U &x,V y){return x>y?x=y,true:false;}
template<typename U,typename V>bool cmax(U &x,V y){return x<y?x=y,true:false;}

int f[50010][N],g[10],h[10];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(6);
    int n=read();
    for(int m=read();m--;)
    {
        int u=read(),v=read();
        g[u]|=1<<v;
        h[v]|=1<<u;
    }
    f[0][0]=1;
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<N;++j)if(f[i][j])
        {
            for(int k=0;k<10;++k)if(~j>>k&1)
            {
                (f[i+1][j&g[k]|h[k]]+=f[i][j])%=p;
            }
        }
    }
    int ans=0;
    for(int i=0;i<N;++i)(ans+=f[n][i])%=p;
    cout<<ans<<'\n';
}

#include <bits/stdc++.h>

constexpr int P = 998244353;

using i64 = long long;

int Normal(int x) {
    if (x < 0) x += P;
    if (x >= P) x -= P;
    return x;
}

template <class Type>
Type Pow(Type a, i64 b) {
    Type res = 1;
    for (; b; b /= 2, a *= a) {
        if (b % 2) res *= a;
    }
    return res;
}

struct Z {
    int x;
    Z(int x = 0) : x(Normal(x)) {}
    Z(i64 x) : x(Normal(x % P)) {}
    int val() const { return x; }
    Z operator-() const { return Z(Normal(P - x)); }
    Z inv() const {
        assert(x != 0);
        return Pow(*this, P - 2);
    }
    Z &operator*=(const Z &rhs) {
        x = i64(x) * rhs.x % P;
        return *this;
    }
    Z &operator+=(const Z &rhs) {
        x = Normal(x + rhs.x);
        return *this;
    }
    Z &operator-=(const Z &rhs) {
        x = Normal(x - rhs.x);
        return *this;
    }
    Z &operator/=(const Z &rhs) { return *this *= rhs.inv(); }
    friend Z operator*(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res *= rhs;
        return res;
    }
    friend Z operator+(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res += rhs;
        return res;
    }
    friend Z operator-(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res -= rhs;
        return res;
    }
    friend Z operator/(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res /= rhs;
        return res;
    }
    friend std::istream &operator>>(std::istream &is, Z &a) {
        i64 v;
        is >> v;
        a = Z(v);
        return is;
    }
    friend std::ostream &operator<<(std::ostream &os, const Z &a) { return os << a.val(); }
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n;
    std::cin >> n;
    int m;
    std::cin >> m;
    std::array<int, 10> bad{};
    for (int i = 0; i < 10; ++i) {
        for (int j = 0; j < 10; ++j) bad[i] |= (i != j) << j;
    }
    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        bad[u] ^= 1 << v;
        bad[v] ^= 1 << u;
    }
    std::array<Z, 1 << 10> f{};
    f.back() = 1;
    for (int i = 0; i < n; ++i) {
        std::array<Z, 1 << 10> g{};
        for (int s = 0; s < (1 << 10); ++s) {
            for (int i = 0; i < 10; ++i) {
                if (s >> i & 1) {
                    int t = (s & ~((1 << i) - 1)) | bad[i];
                    g[t] += f[s];
                }
            }
        }
        f = g;
    }
    auto Ans = std::accumulate(f.begin(), f.end(), Z(0));
    std::cout << Ans << "\n";
    return 0;
}

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

// Template {{{
#define REP(n) for (int _ = 0; _ < (n); _++)
#define FOR(i, a, b) for (int i = a; i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()

template <class T>
bool ckmin(T &a, const T &b) {
  return b < a ? a = b, 1 : 0;
}
template <class T>
bool ckmax(T &a, const T &b) {
  return a < b ? a = b, 1 : 0;
}

namespace std {
template <class Fun>
class y_combinator_result {
  Fun fun_;

  public:
  template <class T>
  explicit y_combinator_result(T &&fun) : fun_(std::forward<T>(fun)) {}

  template <class... Args>
  decltype(auto) operator()(Args &&...args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }
};

template <class Fun>
decltype(auto) y_combinator(Fun &&fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
}  // namespace std

#define DEBUG(x) cerr << #x << ": " << x << '\n'
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p) {
  return os << '(' << p.first << ", " << p.second << ')';
}
template <typename T_container, typename T = typename enable_if<
                                    !is_same<T_container, string>::value,
                                    typename T_container::value_type>::type>
ostream &operator<<(ostream &os, const T_container &v) {
  os << '[';
  string sep;
  for (const T &x : v) os << sep << x, sep = ", ";
  return os << ']';
}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}

const int MOD = 998244353;

void madd(int& a, int b) {
  a += b;
  if (a >= MOD) a -= MOD;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(NULL);
  int N, M; cin >> N >> M;
  const int D = 10;
  vector<int> neighbors(D), smaller_neighbors(D);

  REP(M) {
    int a, b; cin >> a >> b;
    neighbors[a] |= 1<<b;
    neighbors[b] |= 1<<a;
    smaller_neighbors[b] |= 1<<a;
  }

  vector<vector<int>> trans(1<<D, vector<int>(D));
  F0R(mask, 1<<D) {
    F0R(d, D) {
      if (!(mask & (1<<d))) {
        trans[mask][d] = smaller_neighbors[d] | (neighbors[d] & mask);
      }
    }
  }

  vector<vector<int>> dp(2, vector<int>(1<<D, 0));
  dp[0][0] = 1;
  F0R(i, N) {
    F0R(mask, 1<<D) if (dp[0][mask]) {
      F0R(d, D) {
        if (!(mask & (1<<d))) {
          int nmask = trans[mask][d];
          madd(dp[1][nmask], dp[0][mask]);
        }
      }
    }
    F0R(mask, 1<<D) {
      dp[0][mask] = dp[1][mask];
      dp[1][mask] = 0;
    }
  }

  int my_ans = 0;
  F0R(mask, 1<<D) madd(my_ans, dp[0][mask]);
  cout << my_ans << '\n';
}

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

// Template {{{
#define REP(n) for (int _ = 0; _ < (n); _++)
#define FOR(i, a, b) for (int i = a; i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)

#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()

template <class T>
bool ckmin(T &a, const T &b) {
  return b < a ? a = b, 1 : 0;
}
template <class T>
bool ckmax(T &a, const T &b) {
  return a < b ? a = b, 1 : 0;
}

namespace std {
template <class Fun>
class y_combinator_result {
  Fun fun_;

  public:
  template <class T>
  explicit y_combinator_result(T &&fun) : fun_(std::forward<T>(fun)) {}

  template <class... Args>
  decltype(auto) operator()(Args &&...args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }
};

template <class Fun>
decltype(auto) y_combinator(Fun &&fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}
}  // namespace std

#define DEBUG(x) cerr << #x << ": " << x << '\n'
template <typename A, typename B>
ostream &operator<<(ostream &os, const pair<A, B> &p) {
  return os << '(' << p.first << ", " << p.second << ')';
}
template <typename T_container, typename T = typename enable_if<
                                    !is_same<T_container, string>::value,
                                    typename T_container::value_type>::type>
ostream &operator<<(ostream &os, const T_container &v) {
  os << '[';
  string sep;
  for (const T &x : v) os << sep << x, sep = ", ";
  return os << ']';
}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}

const int MOD = 998244353;

void madd(int& a, int b) {
  a += b;
  if (a >= MOD) a -= MOD;
}

const int D = 10;
int trans[1<<D][D];
int dp[2][1<<D];
int neighbors[D], smaller_neighbors[D];

int main() {
  ios_base::sync_with_stdio(false); cin.tie(NULL);
  int N, M; cin >> N >> M;

  REP(M) {
    int a, b; cin >> a >> b;
    neighbors[a] |= 1<<b;
    neighbors[b] |= 1<<a;
    smaller_neighbors[b] |= 1<<a;
  }

  F0R(mask, 1<<D) {
    F0R(d, D) {
      if (!(mask & (1<<d))) {
        trans[mask][d] = smaller_neighbors[d] | (neighbors[d] & mask);
      }
    }
  }

  dp[0][0] = 1;
  F0R(i, N) {
    F0R(mask, 1<<D) {
      F0R(d, D) {
        if (!(mask & (1<<d))) {
          int nmask = trans[mask][d];
          madd(dp[1][nmask], dp[0][mask]);
        }
      }
    }
    F0R(mask, 1<<D) {
      dp[0][mask] = dp[1][mask];
      dp[1][mask] = 0;
    }
  }

  int my_ans = 0;
  F0R(mask, 1<<D) madd(my_ans, dp[0][mask]);
  cout << my_ans << '\n';
}

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

using LL = long long;

template <typename T>
T inverse(T a, T m) {
  T u = 0, v = 1;
  while (a != 0) {
    T t = m / a;
    m -= t * a; swap(a, m);
    u -= t * v; swap(u, v);
  }
  assert(m == 1);
  return u;
}

template <typename T>
class Modular {
 public:
  using Type = typename decay<decltype(T::value)>::type;

  constexpr Modular() : value() {}
  template <typename U>
  Modular(const U& x) {
    value = normalize(x);
  }

  template <typename U>
  static Type normalize(const U& x) {
    Type v;
    if (-mod() <= x && x < mod()) v = static_cast<Type>(x);
    else v = static_cast<Type>(x % mod());
    if (v < 0) v += mod();
    return v;
  }

  const Type& operator()() const { return value; }
  template <typename U>
  explicit operator U() const { return static_cast<U>(value); }
  constexpr static Type mod() { return T::value; }

  Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; }
  Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; }
  template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); }
  template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); }
  Modular& operator++() { return *this += 1; }
  Modular& operator--() { return *this -= 1; }
  Modular operator++(int) { Modular result(*this); *this += 1; return result; }
  Modular operator--(int) { Modular result(*this); *this -= 1; return result; }
  Modular operator-() const { return Modular(-value); }

  template <typename U = T>
  typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) {
#ifdef _WIN32
    uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
    uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
    asm(
      "divl %4; \n\t"
      : "=a" (d), "=d" (m)
      : "d" (xh), "a" (xl), "r" (mod())
    );
    value = m;
#else
    value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
#endif
    return *this;
  }
  template <typename U = T>
  typename enable_if<is_same<typename Modular<U>::Type, long long>::value, Modular>::type& operator*=(const Modular& rhs) {
    long long q = static_cast<long long>(static_cast<long double>(value) * rhs.value / mod());
    value = normalize(value * rhs.value - q * mod());
    return *this;
  }
  template <typename U = T>
  typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) {
    value = normalize(value * rhs.value);
    return *this;
  }

  Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); }

  friend const Type& abs(const Modular& x) { return x.value; }

  template <typename U>
  friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs);

  template <typename U>
  friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs);

  template <typename V, typename U>
  friend V& operator>>(V& stream, Modular<U>& number);

 private:
  Type value;
};

template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; }
template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); }
template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; }

template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); }
template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); }

template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; }

template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; }
template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }

template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; }
template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }

template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; }
template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }

template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; }
template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }

template<typename T, typename U>
Modular<T> power(const Modular<T>& a, const U& b) {
  assert(b >= 0);
  Modular<T> x = a, res = 1;
  U p = b;
  while (p > 0) {
    if (p & 1) res *= x;
    x *= x;
    p >>= 1;
  }
  return res;
}

template <typename T>
bool IsZero(const Modular<T>& number) {
  return number() == 0;
}

template <typename T>
string to_string(const Modular<T>& number) {
  return to_string(number());
}

// U == std::ostream? but done this way because of fastoutput
template <typename U, typename T>
U& operator<<(U& stream, const Modular<T>& number) {
  return stream << number();
}

// U == std::istream? but done this way because of fastinput
template <typename U, typename T>
U& operator>>(U& stream, Modular<T>& number) {
  typename common_type<typename Modular<T>::Type, long long>::type x;
  stream >> x;
  number.value = Modular<T>::normalize(x);
  return stream;
}

using ModType = int;

struct VarMod { static ModType value; };
ModType VarMod::value;
ModType& md = VarMod::value;
using Mint = Modular<VarMod>;

const int MAXN = 50010;

Mint f[MAXN][1 << 10];
int e[10];

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  md = 998244353;
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int a, b;
    cin >> a >> b;
    e[a] |= 1 << b;
    e[b] |= 1 << a;
  }
  f[0][0] = 1;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < 1024; ++j) {
      if (f[i][j] == 0) continue;
      int lo = 10, lomask = 0;
      for (int k = 0; k < 10; ++k) {
        if (j >> k & 1) {
          lo = min(lo, k);
          lomask |= 1 << k;
        }
        if (k <= lo || (e[k] & lomask) == 0) {
          f[i + 1][(1 << k) | (e[k] & j)] += f[i][j];
        }
      }
    }
  }
  Mint ans = 0;
  for (int i = 0; i < 1024; ++i) ans += f[n][i];
  cout << ans << endl;
  return 0;
}

#include <bits/stdc++.h>
constexpr int mod= 998244353;
using i64 = long long;
// assume -P <= x < 2P
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    int m;
    std::cin >> m;

    std::array<int, 10> bad {};
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (i != j) {
                bad[i] |= 1 << j;
            }
        }
    }
    for (int i = 0; i < m; i++) {
        int u, v;
        std::cin >> u >> v;
        bad[u] ^= 1 << v;
        bad[v] ^= 1 << u;
    }

    std::array<int, 1 << 10> f {};
    f[(1<<10)-1]=1;
    for (int i = 0; i < n; i++) {
        std::array<int, 1 << 10> g {};
        for (int s = 0; s < (1 << 10); s++) {
            for (int i = 0; i < 10; i++) {
                if (s >> i & 1) {
                    int t = (s & ~((1 << i) - 1)) | bad[i];
                    g[t] =(g[t]+ f[s])%mod;
                }
            }
        }
        f = g;
    }
    int ans=0;
    for(int i=0;i<(1<<10);i++)
    {
    	ans+=f[i];
    	ans=ans%mod;
	}

    std::cout << ans << "\n";

    return 0;
}

#include <iostream>
#include <cstring>
using namespace std;
const int M=998244353;
int n,m,msk[10];
int f[514],g[514];
int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int u,v;
		cin>>u>>v;
		msk[u]|=1<<v,msk[v]|=1<<u;
	}
	f[0]=1;
	for(int i=1;i<=n;i++){
		memset(g,0,sizeof(g));
		for(int j=0;j<(1<<9);j++)
            if(f[j])
			for(int k=0;k<10;k++)
			if(!((j>>k)&1))
				(g[(j|((1<<k)-1))&msk[k]]+=f[j])%=M;
		memcpy(f,g,sizeof(g));
	}
	int ans=0;
	for(int i=0;i<(1<<9);i++) (ans+=f[i])%=M;
	cout<<ans<<'\n';
}

#pragma GCC optimize ("O3")
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 5e4 + 5;
const int M = 1 << 10;
const int mod = 998244353;
int n, m, g[10][10];
int nxt[10][M], ok[10][M];
int dp[2][M];
int main() {
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin >> n >> m;
    for(int i = 0;i < m;i++) {
        int u, v;
        cin >> u >> v;
        g[u][v] = g[v][u] = true;
    }
    memset(ok, true, sizeof ok);
    for(int digit = 0;digit <= 9;digit++) {
        for(int mask = 0;mask < M;mask++) {
            for(int i = 0;i < digit;i++) {
                if((1 << i) & mask) {
                    if(g[i][digit]) {
                        ok[digit][mask] = false;
                        break;
                    }
                }
            }
            if(ok[digit][mask]) {
                nxt[digit][mask] = (1 << digit);
                for(int i = digit + 1;i < 10;i++)
                    if((1 << i) & mask) {
                        if(g[i][digit])
                            nxt[digit][mask] |= (1 << i);
                    }
            }
        }
    }
    for(int mask = 0;mask < M;mask++)
        dp[n & 1][mask] = 1;
    for(int i = n - 1;i >= 0;i--) {
        memset(dp[i & 1], 0, sizeof dp[i & 1]);
        for(int mask = 0;mask < M;mask++) {
            for(int digit = 0;digit < 10;digit++) {
                if(ok[digit][mask]) {
                    dp[i & 1][mask] = (dp[i & 1][mask] + dp[i & 1 ^ 1][nxt[digit][mask]]) % mod;
                }
            }
        }
    }
    cout << dp[0][0];
    return 0;
}

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <bitset>
#include <vector>
#include <stack>
#include <set>
#include <cstdlib>
#include <unordered_map>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define mp make_pair
#define work system
#define lson tr[now].ls
#define rson tr[now].rs
#define pb push_back
#define debug() cout<<"qwq"<<endl
#define mem(i,a) memset(i,a,sizeof(i))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef double db;
typedef long double ldb;
#define i128 __int128
#define pii pair<int,int>
const db eps=1e-10;
const ll INF = (1ll<<31);
const int siev = 1000000+5;
const int inf = 0x3f3f3f3f;
const ll DMAX = 50000 + 100;
const ll MOD = 998244353;
const ll LMOD = 1000000007;
const int hmod = 202010923;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
template<class T> inline void print(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    int a[20];
    int cnt=0;
    do{
        a[++cnt]=x%10;
        x/=10;
    }while(x>0);
    for(int i=cnt;i>=1;i--){
        putchar(a[i]+'0');
    }
    // putchar(' ');
    puts("");
}
template<class T> inline void read(T &x){
    x=0;
    T f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-'){
            f=-1;
        }
        ch=getchar();
    }
    while(ch<='9' && ch>='0'){
        x=x*10+(ch-'0');
        ch=getchar();
    }
    x*=f;
}
int n;
int m;
ll f[1030],g[1030];
int pre[1030][15];
bool hve[10][10];
void add(ll &a,ll b){
    a=(a+b);
    if(a>=MOD){
        a-=MOD;
    }
}
int main(){
    read(n),read(m);
    int x,y;
    for(int i=1;i<=m;i++){
        read(x),read(y);
        hve[x][y]=hve[y][x]=1;
    }
    int S=(1<<10)-1;
    for(int x=0;x<=S;x++){
        for(int j=0;j<=9;j++){
            int res=0;
            for(int k=0;k<=9;k++){
                if(k<j && hve[k][j]){
                    res |= (1<<k);
                }
                else if(((1<<k) & x)){
                    if(hve[j][k]){
                        res |= (1<<k);
                    }
                }
            }
            pre[x][j]=res;
        }
    }
    f[0]=1;
    for(int i=1;i<=n;i++){
        mem(g,0);
        for(int x=0;x<=S;x++){
            for(int j=0;j<=9;j++){
                if(x & (1<<j)){
                    continue;
                }
                add(g[pre[x][j]],f[x]);
            }
        }
        memcpy(f,g,sizeof(f));
    }
    ll ans=0;
    for(int x=0;x<=S;x++){
        add(ans,f[x]);
    }
    print(ans);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define FORI(i, a, b) for (int (i) = (a); (i) < (b); (i)++)

#define ll long long
#define mp(m, n) make_pair((m), (n))

template<typename T>
void read(vector<T> &t) {FOR(i, t.size()) {cin >> t[i];}}
template<typename T> string tostring(T a) { istringstream sin; sin >> a; return sin.str(); }

// #define DEBUG

#ifdef DEBUG
template<typename T>
void _debug(string s, T x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << *it;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, map<T, K> x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << it->first << ":" << it->second;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, set<T, K> x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << *it;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, vector<pair<T, K> > x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << it->first << "," << it->second;
    }
    cerr << endl;
}

void _debug(string s, int x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, long long x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, double x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, string x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, char x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, size_t x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, bool x) {
    cerr << s << ": " << x << endl;
}

#define debug(x) _debug(#x, (x))
#else
#define debug(x)
#endif

#define db debug

void solve();

void pre_init();

int main() {
    ios_base::sync_with_stdio(false); std::cin.tie(0);
    pre_init();
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
    }
}

void pre_init() {}

long long dp[2][1024];

void solve() {
    int n;
    int m;
    long long mod = 998244353;
    cin >> n >> m;
    vector<vector<long long> > v(10, vector<long long>(10));
    vector<vector<long long> > to(1024);
    FOR(i, m) {
        int a, b;
        cin >> a >> b;
        if (a > b) swap(a, b);
        v[b][a] = v[a][b] = 1;
    }
    cerr << clock() << endl;
    for (int i = 0; i < 1024; i++) {
        for (int j = 0; j < 10; j++) {
            int n_mask = (1 << j);
            bool bad = false;
            for (int k = 0; k < 10; k++) {
                if (((1<<k) & i) && k > j && v[k][j]) bad = true;
                if (((1<<k) & i) && v[k][j]) {
                    n_mask |= (1 << k);
                }
            }
            if (!bad) {
                to[i].push_back(n_mask);
            }
        }
    }
    for (int i = 0; i < 10; i++) dp[0][1<<i] = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 1024; j++) {
            for (int k = 0; k < to[j].size(); k++) {
                dp[i & 1][to[j][k]] += dp[(i-1) & 1][j];
            }
        }
        for (int j = 0; j < 1024; j++) {
            dp[i & 1][j] %= mod;
            dp[(i - 1)&1][j] = 0;
        }
    }
    long long ans = 0;
    FOR (i, 1024) {
        ans += dp[(n - 1) & 1][i];
        ans %= mod;
    }
    cout << ans << endl;
    cerr << clock() << endl;
}

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;

#define F first
#define S second

const int MOD = 998244353;
const int C = 26;//XXX

void add(int &x, int y){
	x += y;
	while (x >= MOD) x -= MOD;
	while (x < 0) x += MOD;
}

const int MAXN = 5e4 + 10;

int n, m, adj[10];

int dp[2][1<<10];
int allow1[10], allow2[10];
void solve() {
    cin >> n >> m;
    for (int i = 0; i < 10; i++)
        adj[i] = 1<<i;
    while (m--) {
        int a, b; cin >> a >> b;
        adj[a] |= 1<<b;
        adj[b] |= 1<<a;
    }
    for (int i = 0; i < 10; i++) {
        allow1[i] = (1<<10)-1 ^ adj[i] ^ 1<<i;
        allow2[i] = (1<<10)-1 ^ allow1[i];
        for (int j = i+1; j<10; j++)
            allow2[i] &= -1 ^ 1<<j;
    }

    int cur = 0;
    dp[cur][(1<<10)-1] = 1;
    for (int i = 0; i < n; i++, cur ^= 1) {
        memset(dp[!cur], 0, sizeof(dp) / 2);  // XXX?
        for (int mask = 1; mask < 1<<10; mask++)
            if (dp[cur][mask])
                for (int j = 0; j < 10; j++)
                    if (mask>>j&1)
                        add(dp[!cur][allow1[j] | allow2[j] & mask], dp[cur][mask]);
    }

    int ans = 0;
    for (int i = 0; i < 1<<10; i++)
        add(ans, dp[cur][i]);
    cout << ans << "\n";
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	//cout << fixed << setprecision(6);

	int te = 1;
	//cin >> te;
	for (int w = 1; w <= te; w++){
		//cout << "Case #" << w << ": ";
		solve();
	}
	return 0;
}

#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eb emplace_back
typedef long long ll;
using namespace std;
const int mod = 998244353;
const int maxn = 50005;
void amod(int &x, int y) {
	x = x + y >= mod ? x + y - mod : x + y;
}
int n, m, g[10][10], f[maxn][1 << 10], w[1 << 10][10];
int main() {
#ifdef DEBUG
	freopen("1.in", "r", stdin);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m;
	for(int i = 1, u, v; i <= m; i++) {
		cin >> u >> v;
		g[u][v] = g[v][u] = 1;
	}
	for(int s = 0; s < (1 << 10); s++) {
		for(int i = 0; i < 10; i++) {
			for(int j = i + 1; j < 10; j++) {
				if((s >> j & 1) && g[i][j]) {
					w[s][i] = -1;
					break;
				}
			}
			if(w[s][i] == -1) {
				continue;
			}
			w[s][i] |= 1 << i;
			for(int j = 0; j < 10; j++) {
				if((s >> j & 1) && g[j][i]) {
					w[s][i] |= 1 << j;
				}
			}
		}
	}
	f[0][0] = 1;
	for(int i = 0; i < n; i++) {
		for(int s = 0; s < (1 << 10); s++) {
			if(!f[i][s]) {
				continue;
			}
			for(int j = 0; j < 10; j++) {
				if(~w[s][j]) {
					amod(f[i + 1][w[s][j]], f[i][s]);
				}
			}
		}
	}
	int ans = 0;
	for(int s = 0; s < (1 << 10); s++) {
		amod(ans, f[n][s]);
	}
	cout << ans << '\n';
	return 0;
}

#include<bits/stdc++.h>
#define endl "\n"

using namespace std;

const int maxn = 50001;
const int mod = 998244353;
long long n, m, k, a, b,t;
const int maxmask = (1<<10)+1;

bool pairs[10][10];

void wczytaj(){
	cin>>n>>m;
	for(int i=0; i<m; i++){
		cin>>a>>b;
		pairs[a][b]=true;
		pairs[b][a]=true;
	}
}

int dp[maxn][maxmask];
int newmask[10][maxmask];
bool f[10][maxmask];

bool find(int c, int mask){
	for(int i=0; i<10; ++i){
		if( (mask&(1<<i)) && pairs[i][c] && i<c)return true;
	}
	return false;
}

int nM(int c, int mask){
	int newmask = (1<<c);
	for(int i=0; i<10; i++){
		if( (mask&(1<<i)) && pairs[i][c]) newmask = (newmask | (1<<i));
	}
	return newmask;
}

void pre(){
	for(int i=0; i<10; i++)for(int mask = 0; mask<(1<<10); ++mask)newmask[i][mask]=nM(i, mask);
	for(int i=0; i<10; i++)for(int mask = 0; mask<(1<<10); ++mask)f[i][mask]=find(i, mask);
}

void solve(){
	for(int i=0; i<10; i++){
		int mask = (1<<i);
		dp[1][mask]=1;
	}
	pre();
	long long res = 0;
	for(int i=1; i<n; i++){for(int mask = 0; mask<(1<<10); ++mask){
		for(int c = 0; c<10; ++c){
			if(f[c][mask])continue;
			int newMask = newmask[c][mask];
			dp[i+1][newMask]= ( dp[i+1][newMask] + dp[i][mask] )%mod;
		}
	}}
	for(int mask = 0; mask<(1<<10); ++mask)res = ( res + dp[n][mask] )%mod ;
	cout<<res;
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	wczytaj();
	solve();
	return 0;
}

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

using ll = long long;
const int inf = 1e9+10;
const ll inf_ll = 1e18+10;
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define cmax(x, y) (x = max(x, y))
#define cmin(x, y) (x = min(x, y))

#ifndef LOCAL
#define debug(...) 0
#else
#include "../../debug.cpp"
#endif

template<ll M>
struct modint {

    static ll _pow(ll n, ll k) {
        ll r = 1;
        for (; k > 0; k >>= 1, n = (n*n)%M)
            if (k&1) r = (r*n)%M;
        return r;
    }

    ll v; modint(ll n = 0) : v(n%M) { v += (M&(0-(v<0))); }

    friend string to_string(const modint n) { return to_string(n.v); }
    friend istream& operator>>(istream& i, modint& n) { return i >> n.v; }
    friend ostream& operator<<(ostream& o, const modint n) { return o << n.v; }
    template<typename T> explicit operator T() { return T(v); }

    friend bool operator==(const modint n, const modint m) { return n.v == m.v; }
    friend bool operator!=(const modint n, const modint m) { return n.v != m.v; }
    friend bool operator<(const modint n, const modint m) { return n.v < m.v; }
    friend bool operator<=(const modint n, const modint m) { return n.v <= m.v; }
    friend bool operator>(const modint n, const modint m) { return n.v > m.v; }
    friend bool operator>=(const modint n, const modint m) { return n.v >= m.v; }

    modint& operator+=(const modint n) { v += n.v; v -= (M&(0-(v>=M))); return *this; }
    modint& operator-=(const modint n) { v -= n.v; v += (M&(0-(v<0))); return *this; }
    modint& operator*=(const modint n) { v = (v*n.v)%M; return *this; }
    modint& operator/=(const modint n) { v = (v*_pow(n.v, M-2))%M; return *this; }
    friend modint operator+(const modint n, const modint m) { return modint(n) += m; }
    friend modint operator-(const modint n, const modint m) { return modint(n) -= m; }
    friend modint operator*(const modint n, const modint m) { return modint(n) *= m; }
    friend modint operator/(const modint n, const modint m) { return modint(n) /= m; }
    modint& operator++() { return *this += 1; }
    modint& operator--() { return *this -= 1; }
    modint operator++(int) { modint t = *this; return *this += 1, t; }
    modint operator--(int) { modint t = *this; return *this -= 1, t; }
    modint operator+() { return *this; }
    modint operator-() { return modint(0) -= *this; }

    // O(logk) modular exponentiation
    modint pow(const ll k) const {
        return k < 0 ? _pow(v, M-1-(-k%(M-1))) : _pow(v, k);
    }
    modint inv() const { return _pow(v, M-2); }
};

using mod = modint<998244353>;

string bin(unsigned long long x) {
    string s(64, '0');
    for (int i = 63; x > 0; i--, x >>= 1)
        if (x&1) s[i] = '1';
    return s;
}

const int B = 10, N = 50005;
mod dp[2][1<<B];

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    ll n, m; cin >> n >> m;
    vector<array<int, 2>> e(m);
    for (int i = 0; i < m; i++)
        cin >> e[i][0] >> e[i][1];
    array<int, B> u, v;
    for (int i = 0; i < B; i++)
        u[i] = v[i] = (1<<B)-1;
    for (auto& [x, y] : e) {
        u[x] &= ~(1<<y);
        u[y] &= ~(1<<x);
        v[max(x, y)] &= ~(1<<min(x, y));
    }
    array<vector<int>, B> t;
    for (int x = 0; x < 1<<B; x++)
        for (int j = 0; j < B; j++)
            if (x&(1<<j))
                t[j].pb(x);
    dp[0][(1<<B)-1] = 1;
    for (int i = 1; i <= n; i++) {
        fill(dp[1], dp[1]+(1<<B), 0);
        for (int j = 0; j < B; j++)
            for (int x : t[j])
                dp[1][(x|u[j])&v[j]] += dp[0][x];
        swap(dp[0], dp[1]);
    }
    mod ans = 0;
    for (int x = 0; x < 1<<B; x++)
        ans += dp[0][x];
    cout << ans << "\n";
}

#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
//#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
using namespace std;
using i64 = long long;
using i128 = __int128;
#define MAXN 50005
#define MAXM 100005
#define K 38
#define MAXP 25
#define MAXK 55
#define MAXC 255
#define MAXERR 105
#define MAXLEN 105
#define MDIR 10
#define MAXR 705
#define BASE 102240
#define MAXA 28
#define MAXT 100005
#define LIMIT 86400
#define MAXV 305
#define OP 0
#define CLO 1
#define DIG 1
#define C1 0
#define C2 1
#define PLUS 0
#define MINUS 1
#define MUL 2
#define CLO 1
#define VERT 1
#define B 31
#define B2 1007
#define W 1
#define H 18
#define SPEC 1
#define MUL 2
#define CNT 3
#define ITER 1000
#define INF 1e18
#define EPS 1e-9
#define MOD 998244353
#define CONST 1000000007
#define FACT 100000000000000
#define PI 3.14159265358979
#define SRC 0
#define pb push_back
#define eb emplace_back
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> ii;
typedef pair<ii,ii> pl;
typedef pair<int,ll> li;
typedef tuple<ll,int,int> iii;
typedef vector<vector<int>> vv;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<ld,int> iv;
typedef vector<ii> vii;
typedef vector<vector<int>> vv;
//typedef complex<double> cd;
#define sc second
#define fr first
#define rep(i,x,y) for (int i = (x); i < (y); ++i)
#define rev(i,x,y) for (int i = (x); i >= (y); --i)
#define LSOne(S) (S & (-S))
#define trav(i,v) for (auto &i : v)
#define foreach(it,v) for (auto it = begin(v); it != end(v); ++it)
#define sortarr(v) sort(begin(v), end(v))

int nxt[15][1026]; //compute next mask to transtion to
bool swp[15][15];
//fix the direction of the swap from smaller digit -> larger digit
//one of the 2 valid candidates can be added
void prep() {
    memset(nxt, -1, sizeof(nxt));
    rep(i, 0, (1 << 10)) {
        rep(j, 0, 10) {
            if (i & (1 << j)) {
                int nmsk = i;
                rep(k, 0, 10) {
                    if (j == k || !swp[j][k]) nmsk |= (1 << k);
                    else if (j > k) nmsk &= ~(1 << k); //if k is not a valid candidate after j is added
                }
                nxt[j][i] = nmsk;
            }
        }
    }
}

int n;
/*
ll memo(int u, int msk) {
    if (u == n) return 1;
    if (dp[u][msk] != -1) return dp[u][msk];
    dp[u][msk] = 0;
    ll &ans = dp[u][msk];
    rep(i, 0, 10) {
        if (msk & (1 << i)) {
            ans = (ans + memo(u + 1, nxt[i][msk])) % MOD;
        }
    }
    return ans;
}
*/
int main() {
    //memset(dp, -1, sizeof(dp));
    int m; cin >> n >> m;
    rep(i, 0, m) {
        int u,v; cin >> u >> v;
        swp[u][v] = swp[v][u] = true;
    }
    prep();
    vector<ll> f((1 << 10) + 5, 0), g((1 << 10) + 5, 0);
    f[(1 << 10) - 1] = 1;
    rep(i,0,n) {
        rep(j,0,g.size()) g[j] = 0;
        rep(j,0,(1<<10)) {
            if (!f[j]) continue;
            rep(k,0,10) {
                if (nxt[k][j] == -1) continue;
                g[nxt[k][j]] = (g[nxt[k][j]] + f[j]) % MOD;
            }
        }
        swap(f,g);
    }
    ll ans = 0;
    rep(i,0,(1<<10)) ans = (ans + f[i]) % MOD;
    cout << ans;
}

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <stdio.h>
#include <math.h>
#include <bitset>
#include <numeric>
#include <deque>
#include <list>
#include <bitset>
#include <array>
#include <tuple>
#include <sstream>
#include <functional>
#include <cmath>
#include <random>
#include <cstring>

using namespace std;
#define pb push_back
#define mp make_pair
#define ifor(a, b) for(int i = a; i < b; ++i)
#define jfor(a, b) for(int j = a; j < b; ++j)
#define kfor(a, b) for(int k = a; k < b; ++k)
#define irof(a, b) for(int i = b - 1; i >= a; --i)
#define jrof(a, b) for(int j = b - 1; j >= a; --j)
#define krof(a, b) for(int k = b - 1; k >= a; --k)
#define all(a) (a).begin(), (a).end()

typedef long long ll;
typedef unsigned long long ull;

const ll MOD = 998244353;

ll mmod(ll x, ll y = MOD) {
    if (x >= 0)
        return x % y;
    return (y - ((-x) % y)) % y;
}

template <ll T = MOD>
struct Res {
    ll value;
    Res() : value(0) {}
    Res(ll val) : value(mmod(val, T)) {}
    Res& operator=(ll val) {
        value = mmod(val, T);
        return *this;
    }
    Res operator+(const Res<T>& other) const {
        return Res(mmod(value + other.value, T));
    }
    Res operator-(const Res<T>& other) const {
        return Res(mmod(value - other.value, T));
    }
    Res operator*(const Res<T>& other) const {
        return Res(mmod(value * other.value, T));
    }
    Res operator+(const Res<T>&& other) const {
        return Res(mmod(value + other.value, T));
    }
    void operator+=(const Res<T>& other) {
        value = mmod(value + other.value, T);
    }
    void operator-=(const Res<T>& other) {
        value = mmod(value - other.value, T);
    }
    Res operator-(const Res<T>&& other) const {
        return Res(mmod(value - other.value, T));
    }
    Res operator*(const Res<T>&& other) const {
        return Res(mmod(value * other.value, T));
    }
    Res pow(ll degree) const {
        degree = degree % (T - 1);
        vector<Res<T>> deg_vals(33);
        deg_vals[0] = *this;
        ifor(1, 33) {
            deg_vals[i] = deg_vals[i - 1] * deg_vals[i - 1];
        }
        Res result = 1;
        for (int i = 0; degree > 0; ++i) {
            if (degree % 2)
                result = result * deg_vals[i];
            degree /= 2;
        }
        return result;
    }
    Res reverse() const {
        return pow(T - 2);
    }
};

//#define graph vector<vector<int>>
//
//graph g1 = { {1, 6}, {0, 2, 3, 5}, {0, 1, 4, 7}, {1, 4}, {2, 3}, {1, 6}, {0, 5}, {2} };
//graph g2 = { {1, 2}, {0, 6}, {0}, {4, 5}, {0, 3}, {3}, {1} };
//graph g3 = { {1}, {2}, {0, 3, 8}, {1, 4}, {6, 8}, {4, 7}, {9}, {6}, {5}, {7} };
//graph g4 = { {1, 2, 3}, {4, 6}, {4, 7}, {5, 8}, {}, {}, {}, {6}, {7} };

int swwap[10];

void solve() {
    int n, m; cin >> n >> m;
    ifor(0, m) {
        int x, y; cin >> x >> y;
        swwap[x] += (1 << y);
        swwap[y] += (1 << x);
    }
    vector dp(2, vector<ll>(1 << 10, -1));
    stack<int> st[2];
    ifor(0, 10) {
        dp[1][1 << i] = 1;
        st[1].push(1 << i);
    }
    vector steps(1 << 10, vector<int>());
    ifor(0, 1 << 10) {
        jfor(0, 10) {
            if (!(i & swwap[j] & ((1 << j) - 1))) {
                steps[i].push_back(i & swwap[j] | (1 << j));
            }
        }
    }
    ifor(1, n) {
        int r = i % 2;
        while(!st[r].empty()) {
            int j = st[r].top();
            st[r].pop();
            for (auto a : steps[j]) {
                if (dp[1 - r][a] == -1) {
                    dp[1 - r][a] = 0;
                    st[1 - r].push(a);
                }
                dp[1 - r][a] = mmod(dp[1 - r][a] + dp[r][j]);
            }
            dp[r][j] = -1;
        }
    }
    Res<> ans = 0;
    while(!st[n%2].empty()) {
        int i = st[n%2].top();
        st[n % 2].pop();
        ans += dp[n % 2][i];
    }
    cout << ans.value << "\n";
}

int main() {
    int t = 1;
    //cin >> t;
    while (t--)
        solve();
    return 0;
}

#line 1 "/home/maspy/compro/library/my_template.hpp"
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using pi = pair<ll, ll>;
using vi = vector<ll>;
using u32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;

template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;
template <class T>
using vvvc = vector<vvc<T>>;
template <class T>
using vvvvc = vector<vvvc<T>>;
template <class T>
using vvvvvc = vector<vvvvc<T>>;
template <class T>
using pq = priority_queue<T>;
template <class T>
using pqg = priority_queue<T, vector<T>, greater<T>>;

#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define vvv(type, name, h, w, ...)   \
  vector<vector<vector<type>>> name( \
      h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)       \
  vector<vector<vector<vector<type>>>> name( \
      a, vector<vector<vector<type>>>(       \
             b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))

// https://trap.jp/post/1224/
#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define FOR4_R(i, a, b, c) for (ll i = (b)-1; i >= ll(a); i -= (c))
#define overload4(a, b, c, d, e, ...) e
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) \
  overload4(__VA_ARGS__, FOR4_R, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define FOR_subset(t, s) for (ll t = s; t >= 0; t = (t == 0 ? -1 : (t - 1) & s))
#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

#define stoi stoll

template <typename T>
T SUM(vector<T> &A) {
  T sum = T(0);
  for (auto &&a: A) sum += a;
  return sum;
}

#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define UB(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

int popcnt(int x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(ll x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
// (0, 1, 2, 3, 4) -> (-1, 0, 1, 0, 2)
int lowbit(int x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(u32 x) { return (x == 0 ? -1 : __builtin_ctz(x)); }
int lowbit(ll x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }
int lowbit(u64 x) { return (x == 0 ? -1 : __builtin_ctzll(x)); }

template <typename T, typename U>
T ceil(T x, U y) {
  return (x > 0 ? (x + y - 1) / y : x / y);
}

template <typename T, typename U>
T floor(T x, U y) {
  return (x > 0 ? x / y : (x - y + 1) / y);
}

template <typename T, typename U>
pair<T, T> divmod(T x, U y) {
  T q = floor(x, y);
  return {q, x - q * y};
}

ll binary_search(function<bool(ll)> check, ll ok, ll ng) {
  assert(check(ok));
  while (abs(ok - ng) > 1) {
    auto x = (ng + ok) / 2;
    if (check(x))
      ok = x;
    else
      ng = x;
  }
  return ok;
}

template <class T, class S>
inline bool chmax(T &a, const S &b) {
  return (a < b ? a = b, 1 : 0);
}
template <class T, class S>
inline bool chmin(T &a, const S &b) {
  return (a > b ? a = b, 1 : 0);
}

vi s_to_vi(const string &S, char first_char) {
  vi A(S.size());
  FOR(i, S.size()) { A[i] = S[i] - first_char; }
  return A;
}

template <typename T>
vector<T> cumsum(vector<T> &A, int off = 1) {
  int N = A.size();
  vector<T> B(N + 1);
  FOR(i, N) { B[i + 1] = B[i] + A[i]; }
  if (off == 0) B.erase(B.begin());
  return B;
}

template <typename CNT, typename T>
vc<CNT> bincount(const vc<T> &A, int size) {
  vc<CNT> C(size);
  for (auto &&x: A) { ++C[x]; }
  return C;
}

template <typename T>
vector<int> argsort(const vector<T> &A) {
  // stable
  vector<int> ids(A.size());
  iota(all(ids), 0);
  sort(all(ids),
       [&](int i, int j) { return A[i] < A[j] || (A[i] == A[j] && i < j); });
  return ids;
}

// A[I[0]], A[I[1]], ...
template <typename T>
vc<T> rearrange(const vc<T> &A, const vc<int> &I) {
  int n = len(A);
  assert(len(I) == n);
  vc<T> B(n);
  FOR(i, n) B[i] = A[I[i]];
  return B;
}
#line 1 "/home/maspy/compro/library/other/io.hpp"
// based on yosupo's fastio
#include <unistd.h>

namespace detail {
template <typename T, decltype(&T::is_modint) = &T::is_modint>
std::true_type check_value(int);
template <typename T>
std::false_type check_value(long);
} // namespace detail

template <typename T>
struct is_modint : decltype(detail::check_value<T>(0)) {};
template <typename T>
using is_modint_t = enable_if_t<is_modint<T>::value>;
template <typename T>
using is_not_modint_t = enable_if_t<!is_modint<T>::value>;

struct Scanner {
  FILE *fp;
  char line[(1 << 15) + 1];
  size_t st = 0, ed = 0;
  void reread() {
    memmove(line, line + st, ed - st);
    ed -= st;
    st = 0;
    ed += fread(line + ed, 1, (1 << 15) - ed, fp);
    line[ed] = '\0';
  }
  bool succ() {
    while (true) {
      if (st == ed) {
        reread();
        if (st == ed) return false;
      }
      while (st != ed && isspace(line[st])) st++;
      if (st != ed) break;
    }
    if (ed - st <= 50) {
      bool sep = false;
      for (size_t i = st; i < ed; i++) {
        if (isspace(line[i])) {
          sep = true;
          break;
        }
      }
      if (!sep) reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ()) return false;
    while (true) {
      size_t sz = 0;
      while (st + sz < ed && !isspace(line[st + sz])) sz++;
      ref.append(line + st, sz);
      st += sz;
      if (!sz || st != ed) break;
      reread();
    }
    return true;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  bool read_single(T &ref) {
    if (!succ()) return false;
    bool neg = false;
    if (line[st] == '-') {
      neg = true;
      st++;
    }
    ref = T(0);
    while (isdigit(line[st])) { ref = 10 * ref + (line[st++] & 0xf); }
    if (neg) ref = -ref;
    return true;
  }
  template <class T, is_modint_t<T> * = nullptr>
  bool read_single(T &ref) {
    long long val = 0;
    bool f = read_single(val);
    ref = T(val);
    return f;
  }
  bool read_single(double &ref) {
    string s;
    if (!read_single(s)) return false;
    ref = std::stod(s);
    return true;
  }
  bool read_single(char &ref) {
    string s;
    if (!read_single(s) || s.size() != 1) return false;
    ref = s[0];
    return true;
  }
  template <class T>
  bool read_single(vector<T> &ref) {
    for (auto &d: ref) {
      if (!read_single(d)) return false;
    }
    return true;
  }
  template <class T, class U>
  bool read_single(pair<T, U> &p) {
    return (read_single(p.first) && read_single(p.second));
  }
  template <class A, class B, class C>
  bool read_single(tuple<A, B, C> &p) {
    return (read_single(get<0>(p)) && read_single(get<1>(p))
            && read_single(get<2>(p)));
  }
  template <class A, class B, class C, class D>
  bool read_single(tuple<A, B, C, D> &p) {
    return (read_single(get<0>(p)) && read_single(get<1>(p))
            && read_single(get<2>(p)) && read_single(get<3>(p)));
  }
  void read() {}
  template <class H, class... T>
  void read(H &h, T &... t) {
    bool f = read_single(h);
    assert(f);
    read(t...);
  }
  Scanner(FILE *fp) : fp(fp) {}
};

struct Printer {
  Printer(FILE *_fp) : fp(_fp) {}
  ~Printer() { flush(); }

  static constexpr size_t SIZE = 1 << 15;
  FILE *fp;
  char line[SIZE], small[50];
  size_t pos = 0;
  void flush() {
    fwrite(line, 1, pos, fp);
    pos = 0;
  }
  void write(const char &val) {
    if (pos == SIZE) flush();
    line[pos++] = val;
  }
  template <class T, enable_if_t<is_integral<T>::value, int> = 0>
  void write(T val) {
    if (pos > (1 << 15) - 50) flush();
    if (val == 0) {
      write('0');
      return;
    }
    if (val < 0) {
      write('-');
      val = -val; // todo min
    }
    size_t len = 0;
    while (val) {
      small[len++] = char(0x30 | (val % 10));
      val /= 10;
    }
    for (size_t i = 0; i < len; i++) { line[pos + i] = small[len - 1 - i]; }
    pos += len;
  }
  void write(const string &s) {
    for (char c: s) write(c);
  }
  void write(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++) write(s[i]);
  }
  void write(const double &x) {
    ostringstream oss;
    oss << setprecision(15) << x;
    string s = oss.str();
    write(s);
  }
  void write(const long double &x) {
    ostringstream oss;
    oss << setprecision(15) << x;
    string s = oss.str();
    write(s);
  }
  template <class T, is_modint_t<T> * = nullptr>
  void write(T &ref) {
    write(ref.val);
  }
  template <class T>
  void write(const vector<T> &val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write(' ');
      write(val[i]);
    }
  }
  template <class T, class U>
  void write(const pair<T, U> &val) {
    write(val.first);
    write(' ');
    write(val.second);
  }
  template <class A, class B, class C>
  void write(const tuple<A, B, C> &val) {
    auto &[a, b, c] = val;
    write(a), write(' '), write(b), write(' '), write(c);
  }
  template <class A, class B, class C, class D>
  void write(const tuple<A, B, C, D> &val) {
    auto &[a, b, c, d] = val;
    write(a), write(' '), write(b), write(' '), write(c), write(' '), write(d);
  }
  template <class A, class B, class C, class D, class E>
  void write(const tuple<A, B, C, D, E> &val) {
    auto &[a, b, c, d, e] = val;
    write(a), write(' '), write(b), write(' '), write(c), write(' '), write(d), write(' '), write(e);
  }
  template <class A, class B, class C, class D, class E, class F>
  void write(const tuple<A, B, C, D, E, F> &val) {
    auto &[a, b, c, d, e, f] = val;
    write(a), write(' '), write(b), write(' '), write(c), write(' '), write(d), write(' '), write(e), write(' '), write(f);
  }
  template <class T, size_t S>
  void write(const array<T, S> &val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
      if (i) write(' ');
      write(val[i]);
    }
  }
  void write(i128 val) {
    string s;
    bool negative = 0;
    if(val < 0){
      negative = 1;
      val = -val;
    }
    while (val) {
      s += '0' + int(val % 10);
      val /= 10;
    }
    if(negative) s += "-";
    reverse(all(s));
    if (len(s) == 0) s = "0";
    write(s);
  }
};

Scanner scanner = Scanner(stdin);
Printer printer = Printer(stdout);

void flush() { printer.flush(); }
void print() { printer.write('\n'); }
template <class Head, class... Tail>
void print(Head &&head, Tail &&... tail) {
  printer.write(head);
  if (sizeof...(Tail)) printer.write(' ');
  print(forward<Tail>(tail)...);
}

void read() {}
template <class Head, class... Tail>
void read(Head &head, Tail &... tail) {
  scanner.read(head);
  read(tail...);
}

#define INT(...)   \
  int __VA_ARGS__; \
  read(__VA_ARGS__)
#define LL(...)   \
  ll __VA_ARGS__; \
  read(__VA_ARGS__)
#define STR(...)      \
  string __VA_ARGS__; \
  read(__VA_ARGS__)
#define CHAR(...)      \
  char __VA_ARGS__; \
  read(__VA_ARGS__)
#define DBL(...)      \
  double __VA_ARGS__; \
  read(__VA_ARGS__)

#define VEC(type, name, size) \
  vector<type> name(size);    \
  read(name)
#define VV(type, name, h, w)                     \
  vector<vector<type>> name(h, vector<type>(w)); \
  read(name)

void YES(bool t = 1) { print(t ? "YES" : "NO"); }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { print(t ? "Yes" : "No"); }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { print(t ? "yes" : "no"); }
void no(bool t = 1) { yes(!t); }
#line 2 "/home/maspy/compro/library/mod/modint.hpp"
template <u32 mod>
struct modint {
  static constexpr bool is_modint = true;
  u32 val;
  constexpr modint(const ll val = 0) noexcept
      : val(val >= 0 ? val % mod : (mod - (-val) % mod) % mod) {}
  bool operator<(const modint &other) const {
    return val < other.val;
  } // To use std::map
  modint &operator+=(const modint &p) {
    if ((val += p.val) >= mod) val -= mod;
    return *this;
  }
  modint &operator-=(const modint &p) {
    if ((val += mod - p.val) >= mod) val -= mod;
    return *this;
  }
  modint &operator*=(const modint &p) {
    val = (u32)(1LL * val * p.val % mod);
    return *this;
  }
  modint &operator/=(const modint &p) {
    *this *= p.inverse();
    return *this;
  }
  modint operator-() const { return modint(get_mod() - val); }
  modint operator+(const modint &p) const { return modint(*this) += p; }
  modint operator-(const modint &p) const { return modint(*this) -= p; }
  modint operator*(const modint &p) const { return modint(*this) *= p; }
  modint operator/(const modint &p) const { return modint(*this) /= p; }
  bool operator==(const modint &p) const { return val == p.val; }
  bool operator!=(const modint &p) const { return val != p.val; }
  modint inverse() const {
    int a = val, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b), swap(u -= t * v, v);
    }
    return modint(u);
  }
  modint pow(int64_t n) const {
    modint ret(1), mul(val);
    while (n > 0) {
      if (n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
  static constexpr u32 get_mod() { return mod; }
};

struct ArbitraryModInt {
  static constexpr bool is_modint = true;
  u32 val;
  ArbitraryModInt() : val(0) {}
  ArbitraryModInt(int64_t y)
      : val(y >= 0 ? y % get_mod()
                   : (get_mod() - (-y) % get_mod()) % get_mod()) {}
  bool operator<(const ArbitraryModInt &other) const {
    return val < other.val;
  } // To use std::map<ArbitraryModInt, T>
  static u32 &get_mod() {
    static u32 mod = 0;
    return mod;
  }
  static void set_mod(int md) { get_mod() = md; }
  ArbitraryModInt &operator+=(const ArbitraryModInt &p) {
    if ((val += p.val) >= get_mod()) val -= get_mod();
    return *this;
  }
  ArbitraryModInt &operator-=(const ArbitraryModInt &p) {
    if ((val += get_mod() - p.val) >= get_mod()) val -= get_mod();
    return *this;
  }
  ArbitraryModInt &operator*=(const ArbitraryModInt &p) {
    unsigned long long a = (unsigned long long)val * p.val;
    unsigned xh = (unsigned)(a >> 32), xl = (unsigned)a, d, m;
    asm("divl %4; \n\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(get_mod()));
    val = m;
    return *this;
  }
  ArbitraryModInt &operator/=(const ArbitraryModInt &p) {
    *this *= p.inverse();
    return *this;
  }
  ArbitraryModInt operator-() const { return ArbitraryModInt(get_mod() - val); }
  ArbitraryModInt operator+(const ArbitraryModInt &p) const {
    return ArbitraryModInt(*this) += p;
  }
  ArbitraryModInt operator-(const ArbitraryModInt &p) const {
    return ArbitraryModInt(*this) -= p;
  }
  ArbitraryModInt operator*(const ArbitraryModInt &p) const {
    return ArbitraryModInt(*this) *= p;
  }
  ArbitraryModInt operator/(const ArbitraryModInt &p) const {
    return ArbitraryModInt(*this) /= p;
  }
  bool operator==(const ArbitraryModInt &p) const { return val == p.val; }
  bool operator!=(const ArbitraryModInt &p) const { return val != p.val; }
  ArbitraryModInt inverse() const {
    int a = val, b = get_mod(), u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b), swap(u -= t * v, v);
    }
    return ArbitraryModInt(u);
  }
  ArbitraryModInt pow(int64_t n) const {
    ArbitraryModInt ret(1), mul(val);
    while (n > 0) {
      if (n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
};

template <typename mint>
tuple<mint, mint, mint> get_factorial_data(int n) {
  static const int mod = mint::get_mod();
  assert(0 <= n && n < mod);
  static vector<mint> fact = {1, 1};
  static vector<mint> fact_inv = {1, 1};
  static vector<mint> inv = {0, 1};
  while (len(fact) <= n) {
    int k = len(fact);
    fact.eb(fact[k - 1] * mint(k));
    auto q = ceil(mod, k);
    int r = k * q - mod;
    inv.eb(inv[r] * mint(q));
    fact_inv.eb(fact_inv[k - 1] * inv[k]);
  }
  return {fact[n], fact_inv[n], inv[n]};
}

template <typename mint>
mint fact(int n) {
  static const int mod = mint::get_mod();
  assert(0 <= n);
  if (n >= mod) return 0;
  return get<0>(get_factorial_data<mint>(n));
}

template <typename mint>
mint fact_inv(int n) {
  static const int mod = mint::get_mod();
  assert(0 <= n && n < mod);
  return get<1>(get_factorial_data<mint>(n));
}

template <typename mint>
mint inv(int n) {
  static const int mod = mint::get_mod();
  assert(0 <= n && n < mod);
  return get<2>(get_factorial_data<mint>(n));
}

template <typename mint, bool large = false>
mint C(ll n, ll k) {
  assert(n >= 0);
  if (k < 0 || n < k) return 0;
  if (!large) return fact<mint>(n) * fact_inv<mint>(k) * fact_inv<mint>(n - k);
  k = min(k, n - k);
  mint x(1);
  FOR(i, k) { x *= mint(n - i); }
  x *= fact_inv<mint>(k);
  return x;
}

template <typename mint, bool large = false>
mint C_inv(ll n, ll k) {
  assert(n >= 0);
  assert(0 <= k && k <= n);
  if (!large) return fact_inv<mint>(n) * fact<mint>(k) * fact<mint>(n - k);
  return mint(1) / C<mint, 1>(n, k);
}

using modint107 = modint<1000000007>;
using modint998 = modint<998244353>;
using amint = ArbitraryModInt;
#line 4 "main.cpp"

using mint = modint998;

void solve() {
  LL(N, M);
  vv(int, G, 11, 11);
  FOR(M) {
    LL(a, b);
    G[a][b] = G[b][a] = 1;
  }

  vc<mint> DP(1 << 10);
  FOR(x, 10) {
    ll can = 0;
    FOR(y, 10) {
      if (x > y && G[x][y]) continue;
      can |= 1 << y;
    }
    DP[can] += mint(1);
  }

  // 遷移リスト
  vc<pi> dat;
  FOR(s, 1 << 10) {
    FOR(x, 10) if (s & 1 << x) {
      ll t = 0;
      // x 以下のもの：swap 不可能なやつだけ認める
      FOR(i, x + 1) if (!G[x][i]) t |= 1 << i;
      // x より大きいもの：swap 不可能なら ok
      FOR(i, x + 1, 10) if (!G[x][i]) t |= 1 << i;
      // x より大きいもの：swap 可能なとき、s に入っていれば ok
      FOR(i, x + 1, 10) if (s & 1 << i) t |= 1 << i;
      dat.eb(s, t);
    }
  }

  FOR(N - 1) {
    vc<mint> newDP(1 << 10);
    for (auto&& [s, t]: dat) { newDP[t] += DP[s]; }
    swap(DP, newDP);
  }
  print(SUM(DP));
}

signed main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << setprecision(15);

  ll T = 1;
  // LL(T);
  FOR(T) solve();

  return 0;
}

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int MS=(1<<10)-1;
const int N=5e4+5;
const int Mod=998244353;

int dp[N][MS+5];
int newS[MS+5][10];
bool edge[10][10];

int main()
{
	int n,m;
	cin >> n >> m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        edge[x][y]=edge[y][x]=true;
    }

    for(int S=0;S<=MS;S++)
    	for(int c=0;c<10;c++)
        {
    		for(int i=0;i<10;i++)
    		{
    			if(!edge[i][c])
    				continue;

    			if(i<c || (S>>i)%2==1)
    				newS[S][c]|=1<<i;
    		}
        }

    dp[0][0]=1;
    for(int i=0;i<n;i++)
    {
        for(int S=0;S<=MS;S++) //前面一定不能取S中包含的位
        	if(dp[i][S])
            {
                for(int c=0;c<10;c++)
                {
                    if((S>>c)%2==1) //S中包含c，就不行
                    	continue;

                    dp[i+1][newS[S][c]]=(dp[i+1][newS[S][c]]+dp[i][S])%Mod;
                }
            }
    }

    int ans=0;
    for(int i=0;i<=MS;i++)
    	ans=(ans+dp[n][i])%Mod;
    printf("%d\n",ans);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f3f3f3f3fll
const int mod = 998244353;
inline void add(int &x, int y)
{
    x += y;
    if (x >= mod)
        x -= mod;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        int m;
        cin >> m;
        vector<vector<bool>> ok(10, vector<bool>(10));
        for (int i = 0; i < m; ++i)
        {
            int x, y;
            cin >> x >> y;
            ok[x][y] = ok[y][x] = true;
        }
        vector<vector<int>> to(1 << 10, vector<int>(10));
        for (int i = 0; i < 1 << 10; ++i)
        {
            for (int j = 0; j < 10; ++j)
            {
                to[i][j] = 1 << j;
                for (int k = 0; k < 10; ++k)
                    if (ok[j][k] && (i >> k & 1))
                    {
                        if (k > j)
                        {
                            to[i][j] = -1;
                            break;
                        }
                        else
                            to[i][j] |= 1 << k;
                    }
            }
        }
        vector<vector<int>> dp(2, vector<int>(1 << 10));
        int u = 0;
        dp[u][0] = 1;
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 0; j < 1 << 10; ++j)
                if (dp[u][j])
                    for (int k = 0; k < 10; ++k)
                        if (to[j][k] != -1)
                            add(dp[u ^ 1][to[j][k]], dp[u][j]);
            dp[u] = vector<int>(1 << 10);
            u ^= 1;
        }
        int ans = 0;
        for (int i = 0; i < 1 << 10; ++i)
            add(ans, dp[u][i]);
        cout << ans << '\n';
    }
}

#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize("O3")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); --i)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) (int) ((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
//const int MOD = (int) 1e9 + 7;
const int MOD = 119 << 23 | 1;
const int FFTMOD = 119 << 23 | 1;
const int INF = (int) 1e9 + 23111992;
const ll LINF = (ll) 1e18 + 23111992;
const ld PI = acos((ld) -1);
const ld EPS = 1e-9;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, int p = MOD) {ll r = 1; for (; k; k >>= 1) {if (k & 1) r = r * n % p; n = n * n % p;} return r;}
template<class T> inline int chkmin(T& a, const T& val) {return val < a ? a = val, 1 : 0;}
template<class T> inline int chkmax(T& a, const T& val) {return a < val ? a = val, 1 : 0;}
inline ull isqrt(ull k) {ull r = sqrt(k) + 1; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + 1; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline void submod(int& a, int val, int p = MOD) {if ((a = (a - val)) < 0) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
int _mult(int x, int y) {return (long long) x * y % MOD;}
template<typename ...Y> int _mult(int x, Y... y) { return (long long) x * _mult(y...) % MOD; }
inline int inv(int a, int p = MOD) {return fpow(a, p - 2, p);}
inline int sign(ld x) {return x < -EPS ? -1 : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
mt19937 mt(chrono::high_resolution_clock::now().time_since_epoch().count());
inline int mrand() {return abs((int) mt());}
inline int mrand(int k) {return abs((int) mt()) % k;}
template<typename X> void debug(X x) { cerr << x << "] "; }
template<typename X, typename ...Y> void debug(X x, Y... y) { cerr << x << " "; debug(y...); }
#define db(...) cerr << "[" << #__VA_ARGS__ << ": ", debug(__VA_ARGS__);
#define endln cerr << "\n";
#define LIKELY(x)   (__builtin_expect(!!(x), 1))
#define UNLIKELY(x) (__builtin_expect(!!(x), 0))

template<const int maxn, const int mod>
struct linear_solver {
    static const long long sqmod = (long long) mod * mod;
    int n;
    int a[maxn], h[maxn], s[maxn], t[maxn];
    long long t_[maxn];

    inline int fpow(int a, long long b) {
        int res = 1;
        while (b) {
            if (b & 1) res = (long long) res * a % mod;
            a = (long long) a * a % mod;
            b >>= 1;
        }
        return res;
    }
    inline vector<int> BM(vector<int> x) {
        vector<int> ls, cur;
        int lf, ld;
        for (int i = 0; i < (int) x.size(); i++) {
            long long t = 0;
            for (int j = 0; j < (int) cur.size(); j++) {
                t += (long long) x[i - j - 1] * cur[j];
                t -= sqmod <= t ? sqmod : 0;
            }
            t %= mod;
            if ((t - x[i]) % mod == 0) continue;
            if (!cur.size()) {
                cur.resize(i + 1);
                lf = i;
                ld = t - x[i];
                ld += ld < 0 ? mod : 0;
                continue;
            }
            int k = (long long) (t - x[i] + mod) * fpow(ld, mod - 2) % mod;
            vector<int> c(i - lf - 1);
            c.push_back(k);
            for (int j = 0; j < (int) ls.size(); j++) {
                c.push_back((long long) k * (mod - ls[j]) % mod);
            }
            if (c.size() < cur.size()) c.resize(cur.size());
            for (int j = 0; j < (int) cur.size(); j++) {
                c[j] += cur[j];
                c[j] -= mod <= c[j] ? mod : 0;
            }
            if (i - lf + (int) ls.size() >= (int) cur.size()) {
                ls = cur, lf = i;
                ld = t - x[i];
                ld += ld < 0 ? mod : 0;
            }
            cur = c;
        }
        for (int i = 0; i < (int) cur.size(); i++) {
            cur[i] = (cur[i] % mod + mod) % mod;
        }
        return cur;
    }
    inline void mult(int* p, int* q) {
        for (int i = 0; i < n + n; i++) t_[i] = 0;
        for (int i = 0; i < n; i++) if (p[i]) {
            for (int j = 0; j < n; j++) {
                t_[i + j] += (long long) p[i] * q[j];
                t_[i + j] -= sqmod <= t_[i + j] ? sqmod : 0;
            }
        }
        for (int i = n + n - 1; n <= i; i--) if (t_[i]) {
            t_[i] %= mod;
            for (int j = n - 1; ~j; j--) {
                t_[i - j - 1] += t_[i] * h[j];
                t_[i - j - 1] -= sqmod <= t_[i - j - 1] ? sqmod : 0;
            }
        }
        for (int i = 0; i < n; i++) p[i] = t_[i] % mod;
    }
    inline long long calc(long long k) {
        for (int i = n; ~i; i--) {
            s[i] = t[i] = 0;
        }
        s[0] = 1;
        if (n != 1) {
            t[1] = 1;
        }
        else {
            t[0] = h[0];
        }
        while (k) {
            if (k & 1) mult(s, t);
            mult(t, t); k >>= 1;
        }
        long long sum = 0;
        for (int i = 0; i < n; i++) {
            sum = (sum + (long long) s[i] * a[i]) % mod;
        }
        return (sum % mod + mod) % mod;
    }
    inline int calc(vector<int> x, long long k) {
        if (k < (int) x.size()) return x[k];
        vector<int> v = BM(x);
        n = v.size();
        if (!n) return 0;
        for (int i = 0; i < n; i++) h[i] = v[i], a[i] = x[i];
        return calc(k);
    }
};
linear_solver<1 << 18, (int) 1e9 + 7> ls;

void chemthan() {
  int n, m; cin >> n >> m;
  vi f(10);
  FOR(i, 0, m) {
    int x, y; cin >> x >> y;
    f[x] |= 1 << y;
    f[y] |= 1 << x;
  }
  vector<vi> nxt(1 << 10);
  FOR(msk, 0, 1 << 10) {
    FOR(i, 0, 10) {
      int flag = 0;
      FOR(j, 0, i) if (bit(msk, j) && bit(f[i], j)) {
        flag = 1;
      }
      if (!flag) {
        int nmsk = (msk & f[i]) | (1 << i);
        nxt[msk].pb(nmsk);
      }
    }
  }
  vi dp(1 << 10);
  dp[0] = 1;
  vi samples;
  FOR(_, 0, n) {
    vi ndp(1 << 10);
    FOR(msk, 0, 1 << 10) {
      for (int nmsk : nxt[msk]) {
        addmod(ndp[nmsk], dp[msk]);
      }
    }
    swap(dp, ndp);
  }
  int res = 0;
  FOR(msk, 0, 1 << 10) addmod(res, dp[msk]);
  cout << res << "\n";
}

int32_t main(int32_t argc, char* argv[]) {
  ios_base::sync_with_stdio(0), cin.tie(0);
  if (argc > 1) {
    assert(freopen(argv[1], "r", stdin));
  }
  if (argc > 2) {
    assert(freopen(argv[2], "wb", stdout));
  }
  int test = 1;
  //cin >> test;
  while (test--)
    chemthan();
  cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
const int MOD = 998244353;

signed main(){
	IOS;

	int n, m; cin >> n >> m;
	vvi adj(10, vi(10));
	vi chk1(10), chk2(10);
	for(int i = 0; i < m; i++){
		int u, v; cin >> u >> v;
		adj[u][v] = adj[v][u] = 1;
	}
	for(int i = 0; i < 10; i++) for(int j = 0; j < 10; j++){
		if(!adj[i][j]) continue;
		if(j < i) chk1[i] |= (1 << j);
		chk2[i] |= (1 << j);
	}
	for(int i = 0; i < 10; i++) adj[i][i] = 1;

	vvi dp(n + 1, vi(1 << 10));
	dp[0][0] = 1;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < (1 << 10); j++){
			if(!dp[i][j]) continue;
			for(int k = 0; k < 10; k++){
				int nxt = j & chk2[k];
				if(j & chk1[k]) continue;
				nxt |= (1 << k);
				dp[i + 1][nxt] += dp[i][j];
				dp[i + 1][nxt] %= MOD;
			}
		}
	}
	int ans = 0;
	for(int i = 0; i < (1 << 10); i++){
		ans += dp[n][i];
		ans %= MOD;
	}
	cout << ans;
}

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

namespace R = ranges;
auto ra(auto x, auto y) { return R::iota_view(x, y); }

using ll = long long;
using ull = long unsigned long;
using ld = double long;

template<int m>
struct modint {
    unsigned x;

    modint() : x(0) {}
    modint(long long arg) : x((arg %= m) < 0 ? arg + m : arg) {}

    modint operator+ (const modint& b) const {
        auto t = *this; t.x = (t.x += b.x) >= m ? t.x-m : t.x; return t;
    }

    modint operator- (const modint& b) const {
        auto t = *this; t.x = (t.x += m-b.x) >= m ? t.x-m : t.x; return t;
    }

    modint operator* (const modint& b) const {
        auto t = *this; t.x = ll(t.x) * b.x % m; return t;
    }

    modint operator/ (const modint& b) const {
        return *this * b.inv();
    }

    modint operator-() const {
        auto t = *this; t.x = x ? m-x : 0; return t;
    }

    template<class T> modint operator^ (T n) const {
        modint t;
        if (n == 0) return t.x = 1, t;
        if (n == 1) return t.x = x, t;
        t = *this ^ (n >> 1); t *= t;
        return n & 1 ? *this * t : t;
    }

    modint& operator+= (const modint& b) { return *this = *this + b; }
    modint& operator-= (const modint& b) { return *this = *this - b; }
    modint& operator*= (const modint& b) { return *this = *this * b; }
    modint& operator/= (const modint& b) { return *this = *this / b; }
    modint& operator++ () { if (++x == m) x = 0; return *this; }
    modint& operator-- () { if (x-- == 0) x = m-1; return *this; }
    modint operator++ (int) { modint tmp = *this; ++*this; return tmp; }
    modint operator-- (int) { modint tmp = *this; --*this; return tmp; }
    bool operator== (const modint& other) const { return x == other.x; }
    bool operator!= (const modint& other) const { return x != other.x; }
    int operator() () const { return x; }
    template<class T> modint operator^= (T n) { return *this = *this ^ n; }
    modint inv() const { return *this ^ (m-2); }
};

const int mod = 998'244'353;
typedef modint<mod> mint;

int can[512][10];
bool g[10][10]; // allowed swaps
int n;

void rdi() {
    cin >> n;

    int m;
    cin >> m;
    for (int i : ra(0, m)) {
        int x, y;
        cin >> x >> y;
        g[x][y] = 1;
        g[y][x] = 1;
    }
}

void pcp() {
    // mask[x] = 1 means x cannot be placed
    // to be more precise, the sequence ends with numbers, all swappable with x
    // such that one of them is greater than x

    for (int mask : ra(0, 512)) {
        for (int x : ra(0, 10)) {
            // can we place x?
            if (mask & (1 << x)) {
                can[mask][x] = -1;
                continue;
            }

            // what is the resulting mask?
            // can we place y after x?
            int mask2 = 0;
            for (int y : ra(0, 9)) {
                bool block;
                if (g[x][y]) {
                    block = (mask & (1 << y)) || (x > y);
                } else {
                    block = false;
                }

                if (block) {
                    mask2 |= 1 << y;
                }
            }

            can[mask][x] = mask2;
        }
    }
}

mint d[2][512];

int main() {
    ios::sync_with_stdio(!cin.tie(0));

    rdi();
    pcp();
    d[0][0] = 1;

    for (int i : ra(0, n)) {
        auto ol = d[i%2];
        auto nu = d[(i+1)%2];
        fill(nu, nu+512, mint{});

        for (int mask : ra(0, 512)) {
            for (int x : ra(0, 10)) {
                if (can[mask][x] != -1) {
                    nu[can[mask][x]] += ol[mask];
                }
            }
        }
    }

    cout << accumulate(d[n%2], d[n%2] + 512, mint{})() << '\n';
}

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

const int S = 10, N = 50002, MOD = 998244353;
int camp[1 << S];
int conn[S][S];
int dp[2][1 << S];
int trans[1 << S][S];
void solve(int case_t) {
  int n, m;
  cin >> n >> m;
  memset(conn, 0, sizeof(conn));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    conn[u][v] = conn[v][u] = 1;
  }
  //计算camp

  memset(camp, -1, sizeof(camp));
  for (int mask = 0; mask < (1 << S); mask++) {
    int minj = 0;
    for (; minj < S; minj++) {
      if (mask & (1 << minj)) break;
    }
    for (int j = minj; j < S; j++) {
      if (!(mask & (1 << j))) continue;
      for (int k = j + 1; k < S; k++) {
        if (conn[j][k] && (camp[mask] & (1 << k))) {
          camp[mask] ^= 1 << k;
        }
      }
    }
  }

  // 计算trans
  memset(trans, 0, sizeof(trans));
  for (int mask = 0; mask < (1 << S); mask++) {
    for (int c = 0; c < S; c++) {
      trans[mask][c] = 1 << c;
      for (int j = 0; j < S; j++) {
        if ((mask & (1 << j)) && conn[c][j]) {
          trans[mask][c] |= 1 << j;
        }
      }
    }
  }
  // dp
  memset(dp, 0, sizeof(dp));
  int cur = 0;
  dp[0][0] = 1;
  // O(n * S * 2^S)
  for (int i = 0; i < n; i++) {
    memset(dp[cur ^ 1], 0, sizeof(dp[0]));
    for (int mask = 0; mask < (1 << S); mask++) {
      if (dp[cur][mask] == 0) continue;
      for (int c = 0; c < S; c++) {
        if (camp[mask] & (1 << c)) {
          dp[cur ^ 1][trans[mask][c]] = (dp[cur ^ 1][trans[mask][c]] + dp[cur][mask]) % MOD;
        }
      }
    }
    cur ^= 1;
  }

  int ans = 0;
  for (int mask = 0; mask < (1 << S); mask++) {
    //if (dp[cur][mask])
      //cout << mask << " " << dp[cur][mask] << endl;
    ans = (ans + dp[cur][mask]) % MOD;
  }

  printf("%d\n", ans);
}

int main() {
  std::ios::sync_with_stdio(false);
  cin.tie(0); cout.tie(0);

  int t = 1;
  //cin >> t;
  while (t--) {
    solve(t);
  }

}

#include <bits/stdc++.h>
#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

using namespace std;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
#define trav(a,x) for (auto& a : x)
#define uid(a, b) uniform_int_distribution<int>(a, b)(rng)

#define vt vector
#define ar array
#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define ins insert

template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ", "; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? ", " : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifdef DEBUG
#define dbg(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif

const int mod = 998244353;

void solve(){
	int n; cin >> n;
	int m; cin >> m;
	vector<vector<bool>> ok(10, vector<bool>(10, false));
	while (m--){
		int u, v; cin >> u >> v;
		ok[u][v] = true;
		ok[v][u] = true;
	}

	vector<vector<int>> nxt(1<<10, vector<int>(10));
	for (int S = 0; S < 1<<10; S++){
		for (int i = 0; i < 10; i++)if (S >> i & 1){
			nxt[S][i] = S;
			for (int j = 0; j < i; j++){
				if (ok[i][j]){
					nxt[S][i] &= ~(1 << j);
				}else{
					nxt[S][i] |= 1 << j;
				}
			}
			for (int j = i+1; j < 10; j++){
				if (!ok[i][j]){
					nxt[S][i] |= 1 << j;
				}
			}
		}
	}
	vector<vector<int>> dp(n+1, vector<int>(1<<10));
	dp[0][(1<<10)-1] = 1;
	for (int i = 0; i < n; i++){
		for (int S = 0; S < (1 << 10); S++)if (dp[i][S]){
			for (int j = 0; j < 10; j++) if (S >> j & 1){
				dp[i+1][nxt[S][j]] += dp[i][S];
				dp[i+1][nxt[S][j]] %= mod;
			}
		}
	}
	cout << accumulate(dp[n].begin(), dp[n].end(), 0LL) % mod;
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    //~ cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

#include <bits/stdc++.h>
#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

using namespace std;

typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;

typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;

typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;

template<class T> using pq = priority_queue<T>;
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;

#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
#define trav(a,x) for (auto& a : x)
#define uid(a, b) uniform_int_distribution<int>(a, b)(rng)

#define vt vector
#define ar array
#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define ins insert

template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}

template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ", "; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? ", " : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifdef DEBUG
#define dbg(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif

const int mod = 998244353;

void solve(){
	int n; cin >> n;
	int m; cin >> m;
	vector<vector<bool>> ok(10, vector<bool>(10, false));
	while (m--){
		int u, v; cin >> u >> v;
		ok[u][v] = true;
		ok[v][u] = true;
	}

	vector<vector<int>> nxt(1<<10, vector<int>(10));
	for (int S = 0; S < 1<<10; S++){
		for (int i = 0; i < 10; i++)if (S >> i & 1){
			nxt[S][i] = S;
			for (int j = 0; j < i; j++){
				if (ok[i][j]){
					nxt[S][i] &= ~(1 << j);
				}else{
					nxt[S][i] |= 1 << j;
				}
			}
			for (int j = i+1; j < 10; j++){
				if (!ok[i][j]){
					nxt[S][i] |= 1 << j;
				}
			}
		}
	}
	vector<vector<int>> dp(n+1, vector<int>(1<<10));
	dp[0][(1<<10)-1] = 1;
	for (int i = 0; i < n; i++){
		for (int S = 0; S < (1 << 10); S++){
			for (int j = 0; j < 10; j++) if (S >> j & 1){
				dp[i+1][nxt[S][j]] += dp[i][S];
				dp[i+1][nxt[S][j]] %= mod;
			}
		}
	}
	cout << accumulate(dp[n].begin(), dp[n].end(), 0LL) % mod;
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    //~ cin >> t;
    while(t--){
        solve();
    }
    return 0;
}

//author: towrist
#include <iostream>
#include <iomanip>
#include <vector>
#include <functional>
#include <cmath>
#include <algorithm>
#include <set>
#include <utility>
#include <queue>
#include <map>
#include <assert.h>
#include <stack>
#include <climits>
#include <string>
#include <ctime>
#include <chrono>
#include <random>
#define int long long int
using namespace std;

/*
sooo coool

dp[mask][i] => number of equivalence classes of length i, such that digits in mask can
be swapped to the front [using some number of swaps independently, for each mask]

lets count the lexicorgraphically minimum element of each equivalence class.

dp[mask][i]

lets say at position [from back] i, we have digit k. then this k can be at pos i of the lexicographical minimum element of equivalence class iff conforms with mask.

and added.
*/

const int mod = 998244353;
const int A = 10;
vector<int> power(A + 1);

void solve()
{
	int n;
	cin >> n;

	int m;
	cin >> m;
	vector<vector<bool>> edge(A, vector<bool>(A, false));

	while (m--)
	{
		int i, j;
		cin >> i >> j;
		edge[i][j] = true;
		edge[j][i] = true;
	}

	vector<vector<int>> nxt_msk(A, vector<int>(power[A], -1));
	for (int mask = 0; mask < power[A]; mask++)
	{
		for (int i = 0; i < A; i++)
		{
			bool ok = true; int nxt = 0;
			for (int z = 0; z < i; z++)
			{
				if (mask & power[z])
				{
					if (edge[i][z]) ok = false;
				}
			}
			if (ok)
			{
				nxt = power[i];
				for (int z = i + 1; z < A; z++)
				{
					if (power[z] & mask)
					{
						if (edge[i][z]) nxt += power[z];
					}
				}
				nxt_msk[i][mask] = nxt;
			}
		}
	}
	vector<int> dp(power[A], 0);
	for (int j = 0; j < A; j++) dp[power[j]] = 1;

	for (int j = 2; j <= n; j++)
	{
		vector<int> new_dp(power[A], 0);
		for (int k = 0; k < A; k++) //the digit which appears as the first digit in the lex min rep of equivalence class of size j
		{
			for (int mask = 0; mask < power[A]; mask++)
			{
				if (nxt_msk[k][mask] != -1)
				{
					new_dp[nxt_msk[k][mask]] += dp[mask];
					if (new_dp[nxt_msk[k][mask]] >= mod) new_dp[nxt_msk[k][mask]] %= mod;
				}
			}
		}
		swap(dp, new_dp);
	}

	int res = 0;
	for (int mask = 0; mask < power[A]; mask++) res += dp[mask];
	cout << res % mod << '\n';

	return;

}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(NULL); cout.tie(NULL);
	int t;
	//cin >> t;
	t = 1;

	power[0] = 1;
	for (int j = 1; j <= A; j++) power[j] = power[j - 1] * 2;

	while (t--)
	{
		solve();
	}
	return 0;
}

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<bitset>
#include<vector>
#include<map>
#include<queue>
using namespace std;
#define re int
inline int read(){
	int x=0,ff=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}
	return x*ff;
}
const int mn=998244353;
inline int ksm(int x,int y=mn-2){
	int s=1;while(y){
		if(y&1)s=1ll*s*x%mn;
		x=1ll*x*x%mn;y>>=1;
	}
	return s;
}
int n,m,p[10],f[1<<10],g[1<<10],qwq[1<<10],awa[1<<10];
inline int md(int x){return x>=mn?x-mn:x;}
signed main(){
	n=read();m=read();int x,y;
	for(re i=1;i<=m;i++){
		x=read();y=read();
		p[x]|=(1<<y);p[y]|=(1<<x);
	}
	qwq[0]=1;awa[0]=0;
	for(re i=1;i<1024;i++){
		awa[i]=awa[i>>1]+(i&1);
		qwq[i]=ksm(awa[i]);
	}
	f[0]=1;
	for(re i=1;i<=n;i++){
		memcpy(g,f,sizeof(f));
		memset(f,0,sizeof(f));
		for(re j=0;j<1024;j++){
			for(re l=0;l<10;l++){
				//if((1<<l)&j)continue;
				f[(j&p[l])|(1<<l)]=md(f[(j&p[l])|(1<<l)]+g[j]);
			}
		}
		for(re j=0;j<1024;j++)f[j]=1ll*f[j]*qwq[j]%mn;
	}
	int ans=0;
	for(re i=0;i<1024;i++)ans=md(ans+f[i]);
	cout<<ans<<endl;
	return 0;
}

// LUOGU_RID: 94417755
#include<bits/stdc++.h>
using namespace std;using ll=long long;const int N=5e4+10,M=10,K=1<<10,mod=998244353;
int n,m,ans,a[M][M],tr[K][M],f[N][K];
int main(){
	cin>>n>>m;for(int u,v;m--;)cin>>u>>v,a[u][v]=a[v][u]=1;
	for(int i=0;i<K;i++){
		for(int j=0;j<10;j++){
			bool flag=1;
			for(int k=j+1;k<10;k++)if((i>>k&1)&&a[j][k]){flag=0;break;}
			if(!flag)continue;
			int t=0;
			for(int k=0;k<10;k++)if(j==k)t|=1<<k;else if((i>>k&1)&&a[k][j])t|=1<<k;
			tr[i][j]=t;
		}
	}
	f[0][0]=1;
	for(int i=0;i<n;i++)
		for(int j=0;j<K;f[i][j]%=mod,j++)
			if(f[i][j])
				for(int k=0;k<10;k++)
					if(tr[j][k])
						(f[i+1][tr[j][k]]+=f[i][j])%=mod;
	for(int i=0;i<K;i++)(ans+=f[n][i]%mod)%=mod;
	cout<<ans;
	return 0;
}

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

#define bit(x) (1 << (x))
const int N = 50005;
const int MOD = 998244353;
const int MX = 11;
int dp[N][1025];
vector<int> can[1025];
bool lin[MX][MX];

template<typename hd, typename tl> void chkmin(hd& a, tl b) { if(b < a) a = b; }
template<typename hd, typename tl> void chkmax(hd& a, tl b) { if(a < b) a = b; }
int n, m;

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n;
	cin >> m;
	for (int i = 0; i < m; i ++) {
		int x, y; cin >> x >> y;
		lin[x][y] = lin[y][x] = 1;
	}
	for (int st = 0; st < bit(10); st ++) {
		bool vis[10];
		for (int j = 0; j < 10; j ++) vis[j] = 0;
		for (int l = 0; l < 10; l ++) {
			int j;
			for (j = 0; j < l; j ++) if (bit(j) & st) {
				if (lin[l][j]) break;
			}
			if (j < l) vis[l] = 1;
		}
		for (int j = 0; j < 10; j ++) if (!vis[j]) {
			int nxtst = bit(j);
			for (int k = j + 1; k < 10; k ++) if (bit(k) & st) {
				if (lin[j][k]) nxtst |= bit(k);
			}
			can[st].push_back(nxtst);
		}
	}
	for (int i = 0; i < 10; i ++) dp[n][bit(i)] = 1;
	for (int i = n - 1; i >= 1; i --) {
		for (int st = 0; st < bit(10); st ++) if (dp[i + 1][st]) {
			for (int j : can[st]) {
				(dp[i][j] += dp[i + 1][st]) %= MOD;
			}
		}
	}
	int rlt = 0;
	for (int i = 0; i < bit(10); i ++) (rlt += dp[1][i]) %= MOD;
	cout << rlt << endl;
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define dbgv(v) cout<<#v<<" = "; f(i,0,v.size()) cout<<v[i]<<" "; cout<<endl
#define dbga(a,x,y) cout<<#a<<" = "; f(i,x,y) cout<<a[i]<<" "; cout<<endl
#define erorp(x) cout<<#x<<"={"<<x.F<<" , "<<x.S<<"}"<<endl
#define eror(x) cout<<#x<<'='<<(x)<<endl
#define f_(i,a,b) for(int i=a;i>=b;i--)
#define f(i,a,b) for(int i=a;i<b;i++)
#define nb(x) __builtin_popcount(x)
#define all(v) v.begin(),v.end()
#define bit(n,k) (((n)>>(k))&1)
#define Add(x,y) x=(x+y)%mod
#define maxm(a,b) a=max(a,b)
#define minm(a,b) a=min(a,b)
#define lst(x) x[x.size()-1]
#define sz(x) int(x.size())
#define mp make_pair
#define ll long long
#define pb push_back
#define S second
#define F first
#define int ll

const int N=1e5+99,mod=998244353;

int n,m,ans,a[N],G[N],dp[2][(1<<10)];

int32_t main(){
	f(i,0,10) f(j,0,10) G[i]|=(1<<j);
	cin>>n>>m;
	f(i,0,m){
		int u,v;
		cin>>u>>v;
		G[u]^=(1<<v);
		G[v]^=(1<<u);
	}
	f(id,0,n){
		int s=id&1;
		dp[s][(1<<10)-2]++;
		f(mask,0,(1<<10)) dp[s^1][mask]=0;
		f(mask,1,(1<<10)){
			int task=mask;
			f_(i,9,0){
				if(bit(task,i+1)) task^=(1<<(i+1));
				if(bit(mask,i)==0) continue ;
				Add(dp[s^1][task|G[i]],dp[s][mask]);
			}
		}
	}
	dp[n&1][0]++;
	f(mask,0,(1<<10)) Add(ans,dp[n&1][mask]);
	cout<<ans;
}

#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 50004, M = 998244353;

int n, m;
int g[10];

int s[(1 << 10)];
int dp[(1 << 10)];

void ph(int& x, int y)
{
    x = (x + y) % M;
}

vector<int> v[(1 << 10)];

void solv()
{
    cin >> n >> m;
    for (int i = 0; i < 10; ++i)
    {
        g[i] = (((1 << 10) - 1) ^ (1 << i));
    }
    for (int ii = 0; ii < m; ++ii)
    {
        int i, j;
        cin >> i >> j;
        g[i] ^= (1 << j);
        g[j] ^= (1 << i);
    }

    for (int x = 0; x < (1 << 10); ++x)
    {
        for (int i = 0; i < 10; ++i)
        {
            if ((x & (1 << i)))
                v[x].push_back(i);
        }
    }

    s[(1 << 10) - 1] = 1;
    for (int ii = 1; ii <= n; ++ii)
    {
        memset(dp, 0, sizeof dp);
        for (int x = 0; x < (1 << 10); ++x)
        {
            for (int i = 0; i < sz(v[x]); ++i)
            {
                ph(dp[(x & (((1 << 10) - 1) ^ ((1 << (v[x][i] + 1)) - 1))) | g[v[x][i]]], s[x]);
            }
        }
        for (int x = 0; x < (1 << 10); ++x)
            ph(s[x], dp[x]);
    }

    int ans = 0;
    for (int x = 0; x < (1 << 10); ++x)
        ans = (ans + dp[x]) % M;
    cout << ans << "\n";
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    ios_base::sync_with_stdio(false), cin.tie(0);

    int tt = 1;
    //cin >> tt;
    while (tt--)
    {
        solv();
    }
    return 0;
}

#include <bits/stdc++.h>

#define rep(i,l,r) for (int i = l; i <= r; i++)
#define per(i,r,l) for (int i = r; i >= l; i--)
#define fi first
#define se second
#define prt std::cout
#define gin std::cin
#define edl std::endl

namespace wxy{

const int N = 5e4 + 50,mod = 998244353;

typedef long long ll;

bool flag[10][1<<10];

int trans[10][1<<10];

int f[N][1<<10],G[10][10],n,m;

bool check(int t,int S) {
    rep(i,0,9) if ((i < t) && (S >> i & 1) && (G[t][i])) return false;
    return true;
}

inline void main(){
    #ifndef ONLINE_JUDGE
        freopen("in.in","r",stdin);
        freopen("out.out","w",stdout);
    #endif
    gin >> n >> m; rep(i,1,m) {int u,v; gin >> u >> v; G[u][v] = G[v][u] = 1;}
    rep(i,0,9) rep(S,0,(1<<10)-1) flag[i][S] = check(i,S);
    rep(i,0,9) rep(S,0,(1<<10)-1) {
        if (!flag[i][S]) continue;
        trans[i][S] = (1<<i);
        rep(k,0,9) if ((S>>k&1)&&(G[i][k])) trans[i][S] |= (1<<k);
    }
    rep(i,0,9) f[1][1<<i] = 1;
    rep(i,1,n-1) rep(S,0,(1<<10)-1) rep(t,0,9) if (flag[t][S])
        f[i+1][trans[t][S]] = (f[i+1][trans[t][S]] + f[i][S]) % mod;
    int res = 0; rep(S,0,(1<<10)-1) res = (res + f[n][S]) % mod;
    prt << res;
}

}signed main(){wxy::main(); return 0;}

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ull unsigned long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
#define FR first
#define SE second
using namespace std;
inline int read() {
    int x = 0; bool op = false;
    char c = getchar();
    while(!isdigit(c))op = (c == '-'), c = getchar();
    while(isdigit(c))x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return op ? -x : x;
}
const int N = 5e4 + 10;
const int P = 998244353;
void add(int &a, int b) {a = (a + b) % P;}
void sub(int &a, int b) {a = (a - b + P) % P;}
int n, m;
int g[15][15], f[N][1 << 10];
vector<int> v[1 << 10];
int main() {
    n = read(); m = read();
    for(int i = 1; i <= m; i++) {
        int x = read(), y = read();
        g[x][y] = g[y][x] = 1;
    }
    for(int i = 0; i < (1 << 10); i++) {
        for(int j = 0; j <= 9; j++) {
            int fl = 1;
            for(int k = 0; k < j; k++) {
                if(g[j][k] && i >> k & 1)fl = 0;
            }
            if(fl == 0)continue;
            int S = (1 << j);
            for(int k = 0; k <= 9; k++) {
                if(i >> k & 1 && g[j][k])S |= (1 << k);
            }
            v[i].pb(S);
        }
    }
    for(int i = 0; i <= 9; i++)f[1][1 << i] = 1;
    for(int i = 2; i <= n; i++) {
        for(int j = 0; j < (1 << 10); j++) {
            if(f[i - 1][j] == 0)continue;
            for(int t : v[j]) {
                add(f[i][t], f[i - 1][j]);
            }
        }
    }
    int ans = 0;
    for(int i = 0; i < (1 << 10); i++)add(ans, f[n][i]);
    printf("%d\n", ans);
    return 0;
}

// LUOGU_RID: 94438489
// Author: Little09
// Problem: Formalism for Formalism
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1679F
// Memory Limit: 250 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int N=10,M=2077;
int n,m;
int g[N][N],f[M][N];
int dp[2][M];
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> n >> m;
	for (int i=1;i<=m;i++)
	{
		int x,y;
		cin >> x >> y;
		g[x][y]=1,g[y][x]=1;
	}
	for (int i=0;i<(1<<10);i++)
	{
		for (int j=0;j<=9;j++)
		{
			if (i&(1<<j))
			{
				f[i][j]=-1;
				continue;
			}
			for (int k=0;k<=9;k++)
			{
				if (g[j][k]==0) continue;
				if (k>j) f[i][j]|=(1<<k);
				else if (i&(1<<k)) f[i][j]|=(1<<k);
			}
		}
	}
	dp[0][0]=1;
	for (int i=1;i<=n;i++)
	{
		for (int j=0;j<(1<<10);j++) dp[i&1][j]=0;
		for (int j=0;j<(1<<10);j++)
		{
			for (int k=0;k<=9;k++)
			{
				if (f[j][k]==-1) continue;
				dp[i&1][f[j][k]]=(dp[i&1][f[j][k]]+dp[i-1&1][j])%mod;
			}
		}
	}
	int ans=0;
	for (int i=0;i<(1<<10);i++) ans=(ans+dp[n&1][i])%mod;
	cout << ans;
	return 0;
}

// LUOGU_RID: 94413845
#include<bits/stdc++.h>
#define fep(i,l,r) for(int i=l;i<=r;++i)
#define feb(i,r,l) for(int i=r;i>=l;--i)
#define For(i,u) for(int i=head[u];i;i=e[i].nxt)
#define ld long double
#define LL long long
//#define int long long
#define pr pair<int,int>
#define mpr make_pair
using namespace std;

const int M = 10,mod = 998244353;
int n,m,f[2][1<<M],mp[M][M],to[1<<M][M];

inline int read()
{
	int s=0,w=1; char ch=getchar();
	while(!(ch>='0'&&ch<='9')) {if(ch=='-') w=-1; ch=getchar();}
	while(  ch>='0'&&ch<='9')  {s=(s<<1)+(s<<3)+ch-'0';; ch=getchar();}
	return s*w;
}
inline int Mod(int x) {return x>=mod?x-mod:x;}
inline void addmod(int &x,int y) {x=Mod(x+y);}

signed main()
{
	n=read(),m=read();
	fep(i,1,m)
	{
		int x=read(),y=read();
		mp[x][y]=mp[y][x]=1;
	}
	fep(S,0,1023)
	{
		fep(i,0,9)
			if((1<<i)&S) to[S][i]=-1;
			else
				fep(j,0,9) if(mp[i][j])
					if(j>i||S&(1<<j)) to[S][i]+=(1<<j);
	}
	int p=0,ans=0; f[0][0]=1;
	fep(T,1,n)
	{
		p^=1;
		fep(S,0,1023)
			fep(i,0,9) if(!((1<<i)&S))
				addmod(f[p][to[S][i]],f[p^1][S]);
		fep(S,0,1023) f[p^1][S]=0;
	}
	fep(S,0,1023) addmod(ans,f[p][S]);
	printf("%d",ans);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
namespace Def{
#define ll long long
#define lll __int128
#define lb long double
#define D double
#define emb emplace_back
#define mkp make_pair
#define Array vector<int>
#define Pair pair<int,int>
#define fi first
#define se second
#define rep(variable,leftrange,rightrange) for(int variable=leftrange;variable<=rightrange;++variable)
#define Rep(variable,leftrange,rightrange) for(int variable=leftrange;variable>=rightrange;--variable)
#define Find(a,b) (lower_bound(a.begin(),a.end(),b)-a.begin())
#define Uniq(v) v.erase(unique(v.begin(),v.end()),v.end())
#define All(x) x.begin(),x.end()
#define nxtl puts("")
#define sq(x) ((x)*(x))
#define lowbit(x) ((x)& -(x))
#define FileIO(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
#define debug(x) puts(#x)
}
namespace IO {
#define MAXSIZE (1<<20)
char *IO_p1,*IO_p2,IO_buf[MAXSIZE];
#ifdef DEBUG
#define gchar() getchar()
#else
#define gchar() (IO_p1==IO_p2&&(IO_p2=(IO_p1=IO_buf)+fread(IO_buf,1,MAXSIZE,stdin),IO_p1==IO_p2)?EOF:*IO_p1++)
#endif
template<typename _Tp>inline void read(_Tp &x){
    x=0;char ch=gchar();
    for(;!isdigit(ch);ch=gchar());
    for(;isdigit(ch);ch=gchar())x=(x<<1)+(x<<3)+(ch^48);
}
template<typename _Tp>inline void nread(_Tp &x){
    x=0;_Tp f=1;char ch=gchar();
    for(;!isdigit(ch);ch=gchar())ch=='-'&&(f=-1);
    for(;isdigit(ch);ch=gchar())x=(x<<1)+(x<<3)+(ch^48);
    x*=f;
}
template<typename _Tp,typename ...Args>
inline void read(_Tp &x,Args &...args){read(x),read(args...);}
template<typename _Tp,typename ...Args>
inline void nread(_Tp &x,Args &...args){nread(x),nread(args...);}
template<typename _Tp>inline void wrt(_Tp x){
    if(x<0)x=-x,putchar('-');
    if(x>9)wrt(x/10);
    putchar(x%10+48);
}
inline void wrt(char ch){putchar(ch);}
template<typename _Tp,typename ...Args>
inline void wrt(_Tp x,Args ...args){wrt(x),wrt(args...);}
#undef MAXSIZE
}
namespace Fast{
    inline void Read(pair<int,int> &x) { IO::read(x.fi,x.se); }
    inline void Read(vector<int> &v,int n){v.resize(n);for(auto &p:v) IO::read(p);}
    inline void Wrt(pair<int,int> x,char c) { IO::wrt(x.fi,' ',x.se,c); }
    inline void Wrt(vector<int> v,char c){for(auto p:v) IO::wrt(p,c);}
    template<typename _Tp>inline void Swap(_Tp &x,_Tp &y) {x^=y^=x^=y;}
    template<typename _Tp>inline _Tp Min(_Tp x,_Tp y){return x<y?x:y;}
    template<typename _Tp>inline _Tp Max(_Tp x,_Tp y){return x>y?x:y;}
    template<typename _Tp>inline void Add(_Tp &x,_Tp y,_Tp p){x+=y;if(x>=p)x-=p;}
    template<typename _Tp>inline void upmax(_Tp &x,_Tp y){if(y>x)x=y;}
    template<typename _Tp>inline void upmin(_Tp &x,_Tp y){if(y<x)x=y;}
}
using namespace IO ;
using namespace Def ;
using namespace Fast ;
const int N = 50003 ;
const int F = 10 ;
const int mod = 998244353 ;
int n , a[F][F] , m;
int nxt[1<<F][F] ;
int trans[F] ;
Array f , nf;
#define fst(x,p) for(int x=0;x<p;++x)
inline void add(int &x,int y) {
    x += y ; x -= x >= mod ? mod : 0 ;
}
signed main()
{
    read(n,m);
    f.resize((1 << F) , 0) ;
    nf.resize((1 << F) , 0) ;
    rep(i,1,m)  {
        int u , v;
        read(u,v);
        a[u][v] = 1;
        a[v][u] = 1;
        trans[u]|=1<<v, trans[v]|=1<<u;
    }
    fst(st,1<<F)
    {
        fst(c,F)
        {
            int flag = 1 ;
            for(int i = F - 1; i > c ; -- i) if((st >> i & 1) && a[i][c]) flag = 0 ;
            if(flag) nxt[st][c] = (st & trans[c]) | (1 << c) ;
            else nxt[st][c] = -1 ;
        }
    }

    // cout << (nxt[2][0]) << '\n' ;

    f[0] = 1;

    rep(i,1,n)  {
        nf.clear() ;
        nf.resize((1 << F) , 0) ;
        fst(st,1<<F)  {
            fst(c,F) {
                if(nxt[st][c] != -1)
                add(nf[nxt[st][c]] , f[st]) ;
            }
        }
        f = nf ;
        // swap(f ,  nf) ;
    }

    int res = 0 ;

    for(int p:f) add(res , p) ;

    wrt(res , '\n') ;

    return 0;
}

#include <bits/stdc++.h>

#define f first
#define s second
#define m_p make_pair
#define vec vector
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define sz(x) (int)(x).size()
#define pw(x) (1LL<<(x))
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
template<class T> bool umax(T &a,const T &b){return (a<b?a=b,1:0);}
template<class T> bool umin(T &a,const T &b){return (a>b?a=b,1:0);}

const int M=998244353;
const int K=10;
const int N=5e4+1;

void add(int &a,int b){
    a+=b;
    if(a>=M) a-=M;
    else if(a<0) a+=M;
}
int mult(int a,int b){
    return 1ll*a*b%M;
}
int dp[2][1<<K];
int gr[1<<K],g[1<<K];
//int g[]
signed main(){
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    int m;
    cin>>m;
    vec<pii> e(m);
    for(auto &z : e){
        cin>>z.f>>z.s;
        if(z.f>z.s)
            swap(z.f,z.s);
        g[z.f]|=(1<<z.s);
        gr[z.f]|=(1<<z.s);
        gr[z.s]|=(1<<z.f);
    }
    dp[0][0]=1;
//    for(int i=0;i<10;i++)
//        g[10][0]=1;
//    sz[cnt]=1;
//    cout<<"C "<<cnt<<endl;

    for(int i=0;i<n;i++){
        int ni=i%2;ni^=1;
        int ki=i%2;
        for(int j=0;j<pw(10);j++)
            dp[ni][j]=0;
        for(int j=0;j<(1<<10);j++){
            for(int t=0;t<10;t++){
                if((g[t]&j)==0)
                    add(dp[ni][(j&gr[t])|(1<<t)],dp[ki][j]);
            }
        }
//        for(int l=0;l<=10;l++){
//
//        }
    }
    int ans=0;
    for(int t=0;t<(1<<10);t++){
        add(ans,dp[n%2][t]);
    }
    cout<<ans;
    return 0;

}
/*
1
4 4
1 2
3 4
1 3
2 4
*/

#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
const int N = 105;
const int mod = 998244353;
int n, m;
int target[N], pre[N], last[10], tot = 0;
void add(int u, int v) {
    target[++tot] = v;
    pre[tot] = last[u];
    last[u] = tot;
}
int dp[50005][1030];
int nxt[1030][10];
vector<int> can[1030];
signed main() {
    scanf("%d%d", &n, &m);
    rep(i, 1, m) {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v); add(v, u);
    }
    rep(S, 0, 1023) {
        rep(i, 0, 9) {
            for (int ptr = last[i]; ptr; ptr = pre[ptr]) {
                int v = target[ptr];
                if (((S >> v) & 1) && v < i) goto ed;
            }
            can[S].push_back(i);
            nxt[S][i] = (1 << i);
            for (int ptr = last[i]; ptr; ptr = pre[ptr]) {
                int v = target[ptr];
                if ((S >> v) & 1 && v > i) nxt[S][i] |= (1 << v);
            }
            ed:;
        }
    }
    dp[0][0] = 1;
    rep(i, 0, n - 1) {
        rep(j, 0, 1023) {
            for (auto x: can[j]) {
                dp[i + 1][nxt[j][x]] = (dp[i + 1][nxt[j][x]] + dp[i][j]) % mod;
            }
        }
    }
    int ans = 0;
    rep(i, 0, 1023) ans = (ans + dp[n][i]) % mod;
    printf("%d\n", ans);
    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <map>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <cassert>
#include <bit>
typedef long long ll;
using namespace std;

//#define int long long

const int mod = 998244353;

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m; cin >> n >> m;
    vector<vector<bool>> st(15, vector<bool> (15, false));
    for (int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        st[u][v] = true;
        st[v][u] = true;
    }

    vector<vector<int>> ha(15, vector<int> ((1 << 10) + 5, 0));
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < (1 << 10); j++) {
            int temp = 0; temp |= (1 << i);
            for (int k = 0; k < 10; k++) {
                if (j & (1 << k) && st[k][i]) {
                    if (k >= i) temp |= (1 << k);
                    else {
                        temp = -1; break;
                    }
                }
            }
            ha[i][j] = temp;
        }
    }

    vector<vector<int>> dp(n + 1, vector<int> ((1 << 10) + 5, 0));
    for (int i = 0; i < 10; i++) {
        dp[1][(1 << i)] = 1;
    }

    for (int i = 1; i < n; i++) {
        for (int k = 0; k < 10; k++) {
            for (int j = 0; j < (1 << 10); j++) {
                if (ha[k][j] != -1) {
                    dp[i + 1][ha[k][j]] += dp[i][j];
                    if (dp[i + 1][ha[k][j]] >= mod) dp[i + 1][ha[k][j]] -= mod;
                }
            }
        }
    }

    ll ans = 0;
    for (int j = 0; j < (1 << 10); j++) {
        ans = (1LL * ans + 1LL * dp[n][j]) % mod;
    }
    cout << ans << endl;
}

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
#define endl '\n'
#define ll long long
#define pi pair<int, int>
#define f first
#define s second

const int mod = 998244353;
const int k = 10;
int n, m;
int a[k], dp[1 << k], dq[1 << k];

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

	cin >> n >> m;

	for(int i = 0, x, y; i < m; i++) cin >> x >> y, a[x] |= 1 << y, a[y] |= 1 << x;

	dp[0] = 1;
	for(int i = 0; i < n; i++){
		memcpy(dq, dp, sizeof(dp));
		memset(dp, 0, sizeof(dp));
		for(int j = 0; j < (1 << k); j++)
		for(int l = 0; l < k; l++){
			if(!((j >> (l + 1)) & (a[l] >> (l + 1)))){
				(dp[(j & a[l]) | (1 << l)] += dq[j]) %= mod;
			}
		}
	}

	ll ret = 0;
	for(int i = 0; i < (1 << k); i++) (ret += dp[i]) %= mod;

	cout << ret << endl;

	return 0;
}

#include<map>
#include<ctime>
#include<cmath>
#include<queue>
#include<bitset>
#include<cstdio>
#include<vector>
#include<random>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll int
using namespace std;
#define I inline ll
#define her1 20090115
#define IV inline void
#define cht 998244353
#define ld long double
#define Aestas16 392699
#define ull unsigned long long
#define mem(x,val)memset(x,val,sizeof x)
#define D(i,j,n)for(register int i=j;i>=n;i--)
#define E(i,now)for(register int i=first[now];i;i=e[i].nxt)
#define F(i,j,n)for(register int i=j;i<=n;i++)
#define DL(i,j,n)for(register ll i=j;i>=n;i--)
#define EL(i,now)for(register ll i=first[now];i;i=e[i].nxt)
#define FL(i,j,n)for(register ll i=j;i<=n;i++)
//#define D(i,j,n)for(int i=j;i>=n;i--)
//#define E(i,now)for(int i=first[now];i;i=e[i].nxt)
//#define F(i,j,n)for(int i=j;i<=n;i++)
//#define DL(i,j,n)for(ll i=j;i>=n;i--)
//#define EL(i,now)for(ll i=first[now];i;i=e[i].nxt)
//#define FL(i,j,n)for(ll i=j;i<=n;i++)
ll read(){
	ll ans=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')ans=ans*10+c-'0',c=getchar();
	return ans*f;
}
mt19937 rnd(her1);
const int M = 1024;
const int maxn = 5e4+5;
IV cadd(ll x,ll&y){y=(y+x)%cht;}
bool getbit(ll x,ll y){return x&(1<<y);}
ll n,m,ans,f[maxn][M],g[M+1][10];bool G[50][50];
int main(){
	n=read();m=read();f[0][0]=1;
	F(i,1,m){ll u=read(),v=read();G[u][v]=G[v][u]=1;}
	F(s,0,1023)F(i,0,9){
		F(t,0,i-1)if(G[i][t]&&getbit(s,t)){g[s][i]=-1;break;}
		if(~g[s][i]){
			g[s][i]=(s|(1<<i));
			F(j,0,8)if(i!=j&&getbit(s,j)&&!G[i][j])g[s][i]^=(1<<j);
		}
	}
	F(i,0,n-1)F(s,0,1023){
		if(!f[i][s])continue;
		F(j,0,9){
			ll v=g[s][j];
			if(~v)cadd(f[i][s],f[i+1][v]);
		}
	}
	F(i,0,1023)cadd(f[n][i],ans);return cout<<ans,0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<numeric>
#include<unordered_set>
#include<unordered_map>
#define fup(i,l,r) for(int i=l;i<=r;i++)
#define fdn(i,l,r) for(int i=r;i>=l;i--)
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pdd pair<double,double>
#define pll pair<ll,ll>
#define pli pair<ll,int>
#define ld long double
#define eps (1e-8)
#define inf (int)(1e9)
#define x first//rem
#define y second//rem
#define maxn 50010//rem
#define mod 998244353//rem
#define mp make_pair
#define pb push_back
using namespace std;

bool up(int &x,int y) { return (x<y?x=y,true:false);}
bool down(int &x,int y) { return (x>y?x=y,true:false); }
void inc(int &x,int y) { x=(x+y)%mod; }
int ksm(int a,int b) { int r=1; for(;b;a=(ll)a*a%mod,b>>=1) if(b&1) r=(ll)r*a%mod; return r; }

int read()
{
	int x=0,flag=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') flag=-flag;
		ch=getchar();
	}
	while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
	return x*flag;
}

int n,m,ans;
int f[maxn][1<<10],s[11],t[11],g[11][11];

int main()
{
	n=read(),m=read();
	fup(i,1,m)
	{
		int x=read(),y=read();
		g[x][y]=g[y][x]=1,s[y]|=(1<<x),t[x]|=(1<<y),t[y]|=(1<<x);
	}

	int S=1023;
	f[1][S]=1;
	fup(i,2,n+1) fup(j,0,S) if(f[i-1][j]) fup(k,0,9) if(j>>k&1)
	{
		int nxt=(S^s[k])&(S^((S^j)&t[k]));
		f[i][nxt]=(f[i][nxt]+f[i-1][j])%mod;
	}
	fup(i,0,S) ans=(ans+f[n+1][i])%mod;
	printf("%d\n",ans);

	return 0;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;

constexpr ll MOD = 998244353;

ll norm(ll x) { return (x % MOD + MOD) % MOD; }
template <class T>
T power(T a, ll b, T res = 1) {
  for (; b; b /= 2, (a *= a) %= MOD)
    if (b & 1) (res *= a) %= MOD;
  return res;
}
struct Z {
  ll x;
  Z(ll _x = 0) : x(norm(_x)) {}
  auto operator<=>(const Z &) const = default;
  Z operator-() const { return Z(norm(MOD - x)); }
  Z inv() const { return power(*this, MOD - 2); }
  Z &operator*=(const Z &rhs) { return x = x * rhs.x % MOD, *this; }
  Z &operator+=(const Z &rhs) { return x = norm(x + rhs.x), *this; }
  Z &operator-=(const Z &rhs) { return x = norm(x - rhs.x), *this; }
  Z &operator/=(const Z &rhs) { return *this *= rhs.inv(); }
  Z &operator%=(const ll &rhs) { return x %= rhs, *this; }
  friend Z operator*(Z lhs, const Z &rhs) { return lhs *= rhs; }
  friend Z operator+(Z lhs, const Z &rhs) { return lhs += rhs; }
  friend Z operator-(Z lhs, const Z &rhs) { return lhs -= rhs; }
  friend Z operator/(Z lhs, const Z &rhs) { return lhs /= rhs; }
  friend Z operator%(Z lhs, const ll &rhs) { return lhs %= rhs; }
  friend auto &operator>>(istream &i, Z &z) { return i >> z.x; }
  friend auto &operator<<(ostream &o, const Z &z) { return o << z.x; }
};

constexpr int SZ = 10;

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cout << fixed << setprecision(20);
  int n, m;
  cin >> n >> m;
  vector g(SZ, vector<int>(SZ));
  for (int i = 0, u, v; i < m; i++) {
    cin >> u >> v;
    g[u][v] = 1, g[v][u] = 1;
  }
  vector to(1 << SZ, vector<int>(SZ, -1));
  for (int mask = 0; mask < (1 << SZ); mask++) {
    for (int i = 0; i < SZ; i++) {
      int f = 1;
      for (int t = 0; t < SZ && f; t++) {
        if (mask & (1 << t) && i > t && g[i][t]) f = 0;
      }
      if (!f) continue;
      int n_mask = (1 << i);
      for (int j = 0; j < SZ; j++) {
        if (g[i][j] && (mask & (1 << j))) n_mask |= (1 << j);
      }
      to[mask][i] = n_mask;
    }
  }
  vector<Z> dp(1 << SZ);
  dp[0] = 1;
  for (int i = 0; i < n; i++) {
    vector<Z> n_dp(1 << SZ);
    for (int mask = 0; mask < (1 << SZ); mask++) {
      for (int c = 0; c < SZ; c++) {
        if (to[mask][c] != -1) {
          n_dp[to[mask][c]] += dp[mask];
        }
      }
    }
    swap(dp, n_dp);
  }
  cout << accumulate(dp.begin(), dp.end(), Z(0)) << "\n";
}

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cassert>
#include <ctime>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define pb push_back
#define mp make_pair
#define fs first
#define sc second

const int mdl = 998244353;
const int maxn = 50 * 1000 + 100;

int n, m;
int ans[2][1 << 10];
bool allowed[10][10];
bool canmove[1 << 10][10];
unsigned int movemask[1 << 10][10];

int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        allowed[u][v] = true;
        allowed[v][u] = true;
    }

    for (int i = 0; i < (1 << 10); i++) {
        for (int j = 0; j < 10; j++) {
            bool can = true;
            unsigned int tg = 1 << j;
            for (int k = 0; k < 10; k++) {
                if ((i >> k) & 1) {
                    if (allowed[k][j] && (k < j)) {
                        can = false;
                    }
                    if (allowed[k][j]) {
                        tg += (1 << k);
                    }
                }
            }

            canmove[i][j] = can;
            movemask[i][j] = tg;
        }
    }

    int cur = 0;
    for (int i = 0; i < 10; i++) {
        ans[0][1 << i] = 1;

    }
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < (1 << 10); j++) {
            ans[cur ^ 1][j] = 0;
        }
        for (int j = 1; j < (1 << 10); j++) {
            if (ans[cur][j] == 0) {
                continue;
            }
            for (int k = 0; k < 10; k++) {
                if (canmove[j][k]) {
                    unsigned int tgm = movemask[j][k];
                    ans[cur ^ 1][tgm] += ans[cur][j];
                    if (ans[cur ^ 1][tgm] >= mdl) {
                        ans[cur ^ 1][tgm] -= mdl;
                    }
                }
            }
        }
        cur ^= 1;
    }
    int res = 0;
    for (int i = 1; i < (1 << 10); i++) {
        res += ans[cur][i];
        if (res >= mdl) {
            res -= mdl;
        }
    }

    cout << res << endl;

    return 0;
}

#include <bits/stdc++.h>

#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast moduler by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    for (long long a : {2, 7, 61}) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define FOR(i, a, b) for (int (i) = (a); (i) <= (b); (i)++)
#define ROF(i, a, b) for (int (i) = (a); (i) >= (b); (i)--)
#define REP(i, n) FOR(i, 0, (n)-1)
#define sqr(x) ((x) * (x))
#define all(x) (x).begin(), (x).end()
#define reset(x, y) memset(x, y, sizeof(x))
#define uni(x) (x).erase(unique(all(x)), (x).end())
#define BUG(x) cerr << #x << " = " << (x) << endl
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define _1 first
#define _2 second
#define chkmin(a, b) a = min(a, b)
#define chkmax(a, b) a = max(a, b)

using mint = atcoder::modint998244353;

const int maxn = 51234;

mint f[maxn][1 << 10];
int n, m, m1[10], m2[10];

int main() {
#ifdef ONLINE_JUDGE
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
#endif
  cin >> n >> m;
  FOR(i, 1, m) {
    int x, y;
    cin >> x >> y;
    m1[x] |= 1 << y;
    m2[y] |= 1 << x;
  }
  f[0][0] = 1;
  FOR(i, 1, n) REP(mask, 1 << 10) if (f[i - 1][mask] != 0) REP(j, 10) if ((mask & (1 << j)) == 0)
    f[i][(mask & m1[j]) | m2[j]] += f[i - 1][mask];
  mint ans = 0;
  REP(mask, 1 << 10) ans += f[n][mask];
  cout << ans.val();
}

#include<bits/stdc++.h>
#define ll long long
#define CHECK(x) cout << (#x) << " is " << (x) << endl;
using namespace std;
// #define int ll
const int MOD = 998244353;
int nxt[(1 << 10)] , n;
int edge[15] , dp[50005][(1 << 10)] , is_valid[(1 << 10)][15];
int sol(int  i,int mask){
	if(i == n) return 1;
	int &ret = dp[i][mask];
	if(~ret) return ret;
	ret = 0;
	for(int j = 0; j < 10; j++){
		int nmask = mask & edge[j];
		nmask |= (1 << j);
		if(nmask >= (1 << (j + 1))) continue;
		ret += sol(i + 1, nmask);
		if(ret >= MOD) ret -= MOD;
	}
	return ret;
}
void solve()
{
	int  m;
	memset(dp , -1,sizeof dp);
	cin >> n >> m;
	for(int i = 0; i < m; i++){
		int x, y;
		cin >> x >> y;
		edge[x] |= (1 << y);
		edge[y] |= (1 << x);
	}
	cout << sol(0 , 0 ) << '\n';

}
int32_t main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	int t=1;
	// cin>>t;
	while(t--) solve();
}

//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define db double
#define vc vector
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#ifdef DEBUG
void debug(){
    cout<<"#\n";
}
template<typename T>void debug(T x){
    cout<<"#"<<x<<'\n';
}
template<typename T>void debug(vc<T> x){
    cout<<'[';for(auto it=x.begin();it!=x.end();++it)
    cout<<*it<<(",]"[it+1==x.end()]);cout<<'\n';
}
template<typename T>void debug(initializer_list<T> x){
    cout<<'[';for(auto it=x.begin();it!=x.end();++it)
    cout<<*it<<(",]"[it+1==x.end()]);cout<<'\n';
}
#else
#define debug(...) 917
#define assert(...) 917
#endif
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

//modint
template<const int P>struct Z{
    int x;Z(LL y=0){if(y>=P||y<=-P)y%=P;if(y<0)y+=P;x=y;}

    friend istream &operator>>(istream& in,Z& z){LL tmp;in>>tmp,z=tmp;return in;}
    friend ostream &operator<<(ostream& out,Z& z){out<<z.x;return out;}
    operator int(){return x;}

    void operator+=(const Z& rht){x+=rht.x;if(x>=P)x-=P;}
    void operator-=(const Z& rht){x-=rht.x;if(x<0)x+=P;}
    void operator*=(const Z& rht){x=1LL*x*rht.x%P;}
    void operator^=(int rht){
        Z res=1;while(rht){if(rht&1)res*=(*this);(*this)*=(*this),rht>>=1;}x=res.x;
    }
    void operator/=(const Z& rht){*this*=rht.inv();}

    Z operator=(LL rht){return *this=Z(rht);}
    Z operator+(Z rht)const{rht+=*this;return rht;}
    Z operator-(Z rht)const{rht=-rht,rht+=*this;return rht;}
    Z operator-()const{return Z(P-x);}
    Z operator*(Z rht)const{rht*=*this;return rht;}
    Z operator^(int rht)const{Z tmp=*this;tmp^=rht;return tmp;}
    Z inv() const{assert(x!=0);return (*this)^(P-2);}
    Z operator/(Z rht)const{rht=rht.inv(),rht*=*this;return rht;}
    bool operator==(Z rht)const{return x==rht.x;}
    bool operator!=(Z rht)const{return x!=rht.x;}
};
using znt =Z<998244353>;

template<const int mod>struct Con{
    using znt=Z<mod>;
    vc<znt> fac,_fac;
    Con(int n):fac(n+1),_fac(n+1){
        fac[0]=1;for(int i=1;i<=n;++i)fac[i]=fac[i-1]*(znt)i;_fac[n]=fac[n].inv();
        for(int i=n-1;i>=0;--i)_fac[i]=_fac[i+1]*(znt)(i+1);
    }
    znt operator()(int n,int m){
        if(n<0||m<0||n<m)return 0;
        return fac[n]*_fac[m]*_fac[n-m];
    }
    znt operator[](int x){return fac[x];}
};

void solve(){
	int n,m;
	Con<998244353> C(10);
    cin>>n>>m;
    vc<vc<int>> g(10,vc<int>(10));
    for(int i=0;i<m;++i){
        int u,v;cin>>u>>v;
        g[u][v]=g[v][u]=1;
    }
    for(int i=0;i<10;++i)g[i][i]=1;
    int MSK=1<<10;
    vc<vc<pair<int,int>>> h(MSK);
    for(int msk=0;msk<MSK;++msk){
        for(int j=0;j<10;++j){
            int msl=msk,tot=0;
            for(int k=0;k<10;++k){
                if((msl>>k&1)&&(g[k][j]==0))msl^=(1<<k),++tot;
            }
            msl|=(1<<j);
            if(msl<(1<<j+1))h[msk].eb(msl,tot);
        }
    }
    vc<vc<znt>> dp(n+1,vc<znt>(MSK));dp[0][0]=1;
    for(int i=0;i<n;++i)for(int msk=0;msk<MSK;++msk){
        for(auto [msl,w]:h[msk])dp[i+1][msl]+=dp[i][msk];
    }
    znt sum=0;
    for(int i=0;i<MSK;++i)sum+=dp[n][i];cout<<sum;
}

int main(){
    #ifndef DEBUG
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	#endif
	int ttt=1;
	for(int i=1;i<=ttt;++i)solve();return 0;
}

#include <vector>
#include <array>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <string>
#include <chrono>
#include <random>
#include <cmath>
#include <cassert>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <sstream>

using namespace std;

class Solution {
public:
    long long solve(int n, vector<pair<int,int>>& E) {
        const static long long MOD = 998244353;

        const int M = 1 << 10;

        vector<vector<int>> nexts(M);

        vector<int> adjs(10);
        for (auto& e : E) {
            int u = e.first, v = e.second;
            adjs[u] |= 1 << v;
            adjs[v] |= 1 << u;
        }

        for (int i = 0; i < M; ++i) {
            for (int j = 0; j < 10; ++j) {
                if (i & ((1 << j) - 1) & adjs[j]) {

                } else {
                    int ni = 1 << j | ((M - 1) ^ ((1 << j) - 1)) & i & adjs[j];
                    nexts[i].push_back(ni);
                }
            }
        }

        vector<long long> dp(M, 0);
        vector<long long> ndp(dp);
        dp[0] = 1;

        for (int i = 0; i < n; ++i) {
            fill(ndp.begin(), ndp.end(), 0);
            for (int j = 0; j < M; ++j) {
                if (dp[j] == 0) {
                    continue;
                }
                for (auto nj : nexts[j]) {
                    ndp[nj] += dp[j];
                    if (ndp[nj] >= MOD) {
                        ndp[nj] -= MOD;
                    }
                }
            }
            swap(dp, ndp);
        }

        long long res = 0;
        for (auto x : dp) {
            res += x;
        }
        res %= MOD;
        return res;
    }
};

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    Solution sol;

    int n;
    int m;
    cin >> n >> m;

    vector<pair<int,int>> P;
    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        P.emplace_back(u, v);
    }

    cout << sol.solve(n, P) << '\n';

    return 0;
}

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

#define _				ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define all(x)			x.begin(), x.end()
#define pb				push_back
#define mp				make_pair
#define F				first
#define S				second
//#define mid				((L + R) >> 1ll)
#define lc				(id << 1ll)
#define rc				(lc | 1ll)
#define debug(x)		cerr << x << endl
#define int				long long

typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
const ll Inf = 1e17 + 10;
const int mod = 998244353;
const int LG = 23;
int n, m, ans;
int a[55][55];
int Mp[(1 << 10) + 10][20], dp[(1 << 10) + 10], pd[(1 << 10) + 10];

int add(int a, int b){
	int c = a + b;
	if(c < 0)
		c += mod;
	if(c >= mod)
		c -= mod;
	return c;
}

inline int mul(int a, int b){
	return 1ll * a * b % mod;
}

inline int pwr(int a, int b){
	int res = 1;
	for( ; b ; b >>= 1ll , a = 1ll * a * a % mod)
		if(b & 1ll)
			res = 1ll * res * a % mod;
	return res;
}

inline int Inv(int a){
	return pwr(a, mod - 2);
}

int32_t main(){_
	cin >> n >> m;
	for(int i = 1 ; i <= m ; i ++){
		int u, v;
		cin >> u >> v;
		a[v][u] = a[u][v] = 1;
	}

	for(int msk = 0 ; msk < (1 << 10) ; msk ++)
		for(int i = 0 ; i <= 9 ; i ++)
			for(int j = 0 ; j <= 9 ; j ++)
				if((j < i || msk & (1 << j)) && a[i][j])
					Mp[msk][i] |= (1 << j);

	dp[0] = 1;
	for(int i = 1 ; i <= n ; i ++){
		memset(pd, 0, sizeof pd);
		for(int msk = 0 ; msk < (1 << 10) ; msk ++)
			if(dp[msk])
				for(int j = 0 ; j <= 9 ; j ++){
					if(msk & (1 << j))
						continue;
					pd[Mp[msk][j]] = add(pd[Mp[msk][j]], dp[msk]);
				}

		for(int j = 0 ; j < (1 << 10) ; j ++)
			dp[j] = pd[j];
	}

	for(int i = 0 ; i < (1 << 10) ; i ++)
		ans = add(ans, dp[i]);

	cout << ans << '\n';
	return 0;
}

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

const int MOD = 998244353;

int add(int a, int b) {
  if (a + b >= MOD) return a + b - MOD;
  return a + b;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  int m;
  cin >> m;
  vector< vector<int> > a(10, vector<int>(10, 0));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    a[u][v] = a[v][u] = 1;
  }
  vector< vector<int> > next(10, vector<int>(1 << 10, 0));
  for (int c = 0; c < 10; c++) {
    for (int mask = 0; mask < (1 << 10); mask++) {
      next[c][mask] |= (1 << c);
      for (int i = c + 1; i < 10; i++) {
        if ((mask & (1 << i)) && a[c][i]) next[c][mask] |= (1 << i);
      }
      for (int i = 0; i < c; i++) {
        if ((mask & (1 << i)) && a[c][i]) next[c][mask] = -1;
      }
    }
  }
  vector< vector<int> > dp(n + 1, vector<int>(1 << 10, 0));
  dp[0][0] = 1;
  for (int suff = 0; suff < n; suff++) {
    for (int mask = 0; mask < (1 << 10); mask++) {
      for (int c = 0; c < 10; c++) {
        if (next[c][mask] != -1) dp[suff + 1][next[c][mask]] = add(dp[suff + 1][next[c][mask]], dp[suff][mask]);
      }
    }
  }
  int ans = 0;
  for (int mask = 0; mask < (1 << 10); mask++) ans = add(ans, dp[n][mask]);
  cout << ans << '\n';
  return 0;
}

#include<bits/stdc++.h>
#define forn(i,a,b)for(int i=(a),_b=(b);i<=_b;i++)
#define fore(i,b,a)for(int i=(b),_a=(a);i>=_a;i--)
#define rep(i,n)for(int i=0,_n=n;i<n;i++)
#define ll long long
#define pii pair<int,int>
#define m_p make_pair
#define pb push_back
#define fi first
#define se second
#define foreach(i,c) for(__typeof(c.begin())i=(c.begin());i!=(c).end();i++)
using namespace std;
const int N=50010,mod=998244353;
int n,m;
int a[10];
int dp[N][1024];
int main(){
    cin.tie(0);cout.tie(0);
	ios::sync_with_stdio(0);
	cin>>n>>m;
	rep(i,m){
		int x,y;cin>>x>>y;
		a[y]|=(1<<x);
	}
	dp[0][0]=1;
	forn(i,1,n){
		rep(msk,1<<10){
			rep(j,10){
				if((msk>>j)&1)continue;
				dp[i][msk|a[j]]+=dp[i-1][msk];
				dp[i][msk|a[j]]%=mod;
			}
		}
	}
	int ans=0;
	rep(i,1<<10){
		ans+=dp[n][i];ans%=mod;
	}
	cout<<ans<<"\n";
	return 0;
}

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

const int mod = 998244353;
const int Maxn = 50005;
const int Maxd = 10;

int n;
int m;
bool E[Maxd][Maxd];
bool good[1 << Maxd][Maxd];
int nxt[1 << Maxd][Maxd];
int cur, dp[2][1 << Maxd];

int main()
{
    scanf("%d", &n);
    scanf("%d", &m);
    for (int i = 0; i < Maxd; i++)
        E[i][i] = true;
    for (int i = 0; i < m; i++) {
        int a, b; scanf("%d %d", &a, &b);
        E[a][b] = E[b][a] = true;
    }
    for (int i = 0; i < 1 << Maxd; i++)
        for (int j = 0; j < Maxd; j++) {
            bool fall = false;
            for (int k = 0; k < Maxd; k++) if (i & 1 << k)
                if (!E[j][k]) break;
                else if (k > j) { fall = true; break; }
            good[i][j] = !fall;
            int ni = i;
            ni |= 1 << j;
            nxt[i][j] = ni;
        }
    dp[cur][0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 1 << Maxd; j++) if (dp[cur][j]) {
            int ways = dp[cur][j]; dp[cur][j] = 0;
            for (int k = 0; k < Maxd; k++) if (good[j][k])
                dp[!cur][nxt[j][k]] = (dp[!cur][nxt[j][k]] + ways) % mod;
        }
        cur = !cur;
    }
    int res = 0;
    for (int j = 0; j < 1 << Maxd; j++)
        res = (res + dp[cur][j]) % mod;
    printf("%d\n", res);
    return 0;
}

#include<bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define fi first
#define se second
#define min amin
#define max amax
#define pb push_back
using namespace std;
using ll=long long;
using pii=array<int,2>;
constexpr int N=5E4+10,M=10;
constexpr int inf=1E9;
constexpr int p=998244353;
int qpow(int x,int n=p-2){int y=1;for(;n;n>>=1,x=1LL*x*x%p)if(n&1)y=1LL*y*x%p;return y;}
template<typename T=int>T read(){T x;cin>>x;return x;}
template<typename U,typename V>auto min(U x,V y){return x<y?x:y;}
template<typename U,typename V>auto max(U x,V y){return x>y?x:y;}
template<typename U,typename...V>auto min(U x,V...y){return min(x,min(y...));}
template<typename U,typename...V>auto max(U x,V...y){return max(x,max(y...));}
template<typename U,typename V>bool cmin(U &x,V y){return x>y?x=y,true:false;}
template<typename U,typename V>bool cmax(U &x,V y){return x<y?x=y,true:false;}

int fac[N],inv[N];
int fa[M],f[M],q[M],s;
bool b[M][M];
int c(int n,int m){return 1LL*fac[n]*inv[m]%p*inv[n-m]%p;}
int find(int x){return fa[x]^x?fa[x]=find(fa[x]):x;}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(6);
    int n=read();
    fac[0]=1;
    for(int i=1;i<=n;++i)fac[i]=1LL*fac[i-1]*i%p;
    inv[n]=qpow(fac[n]);
    for(int i=n;i>=1;--i)inv[i-1]=1LL*inv[i]*i%p;
    for(int m=read();m--;b[read()][read()]=1);
    int ans=0;
    for(int i=1<<M;--i;)
    {
        s=0;
        for(int j=0;j<M;++j)if(i>>j&1)fa[q[s++]=j]=j;
        if(s>n)continue;
        int res=c(n-1,s-1);
        for(int j=0;j<s;++j)for(int k=0;k<j;++k)if(b[q[k]][q[j]])fa[find(q[k])]=find(q[j]);
        for(int j=0;j<s;++j)++f[find(q[j])];
        for(int j=0;j<M;++j)if(f[j])
        {
            res=1LL*res*c(s,f[j])%p;
            s-=f[j];
            f[j]=0;
        }
        (ans+=res)%=p;
    }
    cout<<ans<<'\n';
}

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define M 51
#define N 50010
#define W 11
#define Z 1100
#define yu 998244353
ll n,m,u[M],v[M];
ll cha[W][Z],o[W][W];
ll f[N][Z];
ll gm[Z];
inline void push(ll &x,ll y)
{
	if(y>=yu)y=y%yu;
	if(y<0)y=(y%yu+yu)%yu;
	x+=y;
	if(x>yu)x-=yu;
	return ;
}
int main()
{
	//freopen("1.txt","r",stdin);
	cin>>n;
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>u[i]>>v[i];
		o[u[i]][v[i]]=1;
		o[v[i]][u[i]]=1;
	}
	for(int i=0;i<W-1;i++)
	{
		for(int j=0;j<(1<<(W-1));j++)
		{
			ll kz=0;
			for(int k=0;k<W-1;k++)
			{
				if(((1<<k)&j)>0)
				{
					if(o[i][k])
					{
						kz=1;
						cha[i][j]=0;
					}
					gm[j]=k;
				}
			}
			if(!kz)cha[i][j]=1;
		}
	}
	f[0][0]=1;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<(1<<(W-1));j++)
		{
			if(!f[i][j])continue;
			for(int k=0;k<W-1;k++)
			{
				if(cha[k][j])
				{
					push(f[i+1][(1<<(k))],f[i][j]);
				}else
				{
					if(k<gm[j])continue;
					push(f[i+1][j|(1<<(k))],f[i][j]);
				}
			}
		}
	}
	ll ans=0;
	for(int j=0;j<(1<<(W-1));j++)
	{
		push(ans,f[n][j]);
	}
	cout<<ans;
	return 0;
}

#include <bits/stdc++.h>
#define ld long double
#define ll long long int
#define st first
#define nd second
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define mt make_tuple

using namespace std;

const int mod = 998244353;
int n, m;
bool comp[10][10];
bool canGoAfter[10][10];
int dp[55555][10];

void solve(){
    cin >> n >> m;
    for(int i=1;i<=m;i++){
        int x, y; cin >> x >> y;
        comp[x][y] = comp[y][x] = true;
    }
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            if(j >= i || !comp[i][j]) canGoAfter[i][j] = true;
        }
    }
    for(int i=0;i<10;i++) dp[1][i] = 1;
    for(int i=1;i<n;i++){
        for(int j=0;j<10;j++){
            for(int k=0;k<10;k++){
                if(canGoAfter[j][k]){
                    dp[i + 1][k] += dp[i][j];
                    dp[i + 1][k] %= mod;
                }
            }
        }
    }
    int ans = 0;
    for(int i=0;i<10;i++){
        ans += dp[n][i];
        ans %= mod;
    }
    cout << ans << "\n";
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);

    int tt = 1;
    //cin >> tt;
    while(tt--) solve();

    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define dbgv(v) cout<<#v<<" = "; f(i,0,v.size()) cout<<v[i]<<" "; cout<<endl
#define dbga(a,x,y) cout<<#a<<" = "; f(i,x,y) cout<<a[i]<<" "; cout<<endl
#define erorp(x) cout<<#x<<"={"<<x.F<<" , "<<x.S<<"}"<<endl
#define eror(x) cout<<#x<<'='<<(x)<<endl
#define f_(i,a,b) for(int i=a;i>=b;i--)
#define f(i,a,b) for(int i=a;i<b;i++)
#define nb(x) __builtin_popcount(x)
#define all(v) v.begin(),v.end()
#define bit(n,k) (((n)>>(k))&1)
#define Add(x,y) x=(x+y)%mod
#define maxm(a,b) a=max(a,b)
#define minm(a,b) a=min(a,b)
#define lst(x) x[x.size()-1]
#define sz(x) int(x.size())
#define mp make_pair
#define ll long long
#define pb push_back
#define S second
#define F first
#define int ll

const int N=1e5+99,mod=998244353;

int n,m,ans,a[N],G[N],dp[2][(1<<10)];

int32_t main(){
	f(i,0,10) f(j,0,10) G[i]|=(1<<j);
	cin>>n>>m;
	f(i,0,m){
		int u,v;
		cin>>u>>v;
		G[u]^=(1<<v);
		G[v]^=(1<<u);
	}
	f(id,0,n){
		int s=id&1;
		dp[s][(1<<10)-2]++;
		f(mask,0,(1<<10)) dp[s^1][mask]=0;
		f(mask,1,(1<<10)){
			int task=mask;
			f_(i,9,0){
				if(bit(task,i+1)) task^=(1<<(i+1));
				if(bit(mask,i)==0) continue ;
				Add(dp[s^1][task|G[i]],dp[s][mask]);
			}
		}
	}
	dp[n&1][0]++;
	f(mask,0,(1<<10)) ans+=dp[n&1][mask];
	cout<<ans;
}

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cassert>
#include <ctime>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define pb push_back
#define mp make_pair
#define fs first
#define sc second

const int mdl = 998244353;
const int maxn = 50 * 1000 + 100;

int n, m;
int ans[maxn][10];
bool allowed[10][10];

int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        allowed[u][v] = true;
        allowed[v][u] = true;
    }

    for (int i = 0; i < 10; i++) {
        ans[1][i] = 1;
    }
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 10; j++) {
            for (int k = 0; k < 10; k++) {
                if (!allowed[j][k] || j <= k) {
                    ans[i + 1][k] += ans[i][j];
                    if (ans[i + 1][k] >= mdl) {
                        ans[i + 1][k] -= mdl;
                    }
                }
            }
        }
    }
    int res = 0;
    for (int i = 0; i < 10; i++) {
        res += ans[n][i];
        if (res >= mdl) {
            res -= mdl;
        }
    }

    cout << res << endl;

    return 0;
}

#include<bits/stdc++.h>
#define ls i<<1
#define rs i<<1|1
#define fi first
#define se second
#define min amin
#define max amax
#define pb push_back
using namespace std;
using ll=long long;
using pii=array<int,2>;
constexpr int N=5E4+10,S=512;
constexpr int inf=1E9;
constexpr int p=998244353;
int qpow(int x,int n=p-2){int y=1;for(;n;n>>=1,x=1LL*x*x%p)if(n&1)y=1LL*y*x%p;return y;}
template<typename T=int>T read(){T x;cin>>x;return x;}
template<typename U,typename V>auto min(U x,V y){return x<y?x:y;}
template<typename U,typename V>auto max(U x,V y){return x>y?x:y;}
template<typename U,typename...V>auto min(U x,V...y){return min(x,min(y...));}
template<typename U,typename...V>auto max(U x,V...y){return max(x,max(y...));}
template<typename U,typename V>bool cmin(U &x,V y){return x>y?x=y,true:false;}
template<typename U,typename V>bool cmax(U &x,V y){return x<y?x=y,true:false;}

int f[N][S],h[10];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout<<fixed<<setprecision(6);
    int n=read();
    for(int m=read();m--;h[read()]|=1<<read());
    f[0][0]=1;
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<S;++j)if(f[i][j])
        {
            for(int k=0;k<10;++k)if(~j>>k&1)
            {
                (f[i+1][j|h[k]]+=f[i][j])%=p;
            }
        }
    }
    int ans=0;
    for(int i=0;i<S;++i)(ans+=f[n][i])%=p;
    cout<<ans<<'\n';
}

#include<cstdio>
#include<algorithm>
using namespace std;

#define ll long long int
#define mod 998244353
int inc(int a,int b)
{
	return (a+b<mod)?a+b:a+b-mod;
}
int dec(int a,int b)
{
	return (a<b)?a-b+mod:a-b;
}
int mul(int a,int b)
{
	return (int)((ll)a*b%mod);
}
int pow(int a,int b)
{
	int res=1;
	while(b>0){
		if(b&1) res=mul(res,a);
		a=mul(a,a); b>>=1;
	}
	return res;
}
int inv(int x)
{
	return pow(x,mod-2);
}

int n,m,can[10][10];
int dp[50000][10];

int main(void)
{
	scanf("%d%d",&n,&m);
	while(m--){
		int v1,v2;
		scanf("%d%d",&v1,&v2);
		can[v1][v2]=can[v2][v1]=1;
	}
	for(int i=0;i<10;i++)
		dp[0][i]=1;
	for(int i=1;i<n;i++)
		for(int j=0;j<10;j++){
			dp[i][j]=0;
			for(int k=0;k<10;k++)
				if(!can[j][k]||k<=j)
					dp[i][j]=inc(dp[i][j],dp[i-1][k]);
		}
	int ans=0;
	for(int i=0;i<10;i++)
		ans=inc(ans,dp[n-1][i]);
	printf("%d\n",ans);
	return 0;
}

#include <bits/stdc++.h>
#define int long long
#define rep(i,bbb,eee) for(int i=bbb;i<=eee;i++)
#define frep(i,bbb,eee) for(int i=bbb;i>=eee;i--)
#define mem(a,b) memset(a,b,sizeof(a))
#define all(bbb) (bbb).begin(),(bbb).end()
#define cout(xxx) cout<<fixed<<setprecision(xxx)
#define endl "\n"
#define fread freopen("in.txt", "r", stdin)
#define inf 0x3f3f3f3f
#define pb push_back
#define AC signed
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<PII,int> PIII;
const int N=50010,M=998244353;
inline int read(){int x=0,f=1;char ch=getchar();while(!isdigit(ch)&&ch!='-')ch=getchar();if(ch=='-')f=-1,ch=getchar();while(isdigit(ch))x=x*10+ch-'0',ch=getchar();return f*x;}
inline void print(int x){if(x<0){putchar('-');x=-x;}if(x>9) print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return b ? gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
int qmi(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)res=res*a%M;
        a=a*a%M;
        b>>=1;
    }
    return res%M;
}
//____________________________________________//
int S=10;
int n,m,f[2][1<<10],camp[1<<10],g[1<<10][10],vis[10][10];
void solve()
{
	cin>>n>>m;
	rep(i,1,m)
	{
		int u,v;
		cin>>u>>v;
		vis[u][v]=vis[v][u]=1;
	}
	mem(camp,-1);
	for(int b=0;b<(1<<S);b++)
	{
		for(int i=0;i<S;i++)
		{
			if(!(b>>i&1))continue;
			for(int j=i+1;j<S;j++)
			{
				if(vis[i][j]&&camp[b]>>j&1)camp[b]^=(1<<j);
			}
		}
	}
	for(int b=0;b<(1<<S);b++)
	{
		for(int c=0;c<S;c++)
		{
			g[b][c]=1<<c;
			for(int i=0;i<S;i++)
			{
				if(vis[c][i]&&b>>i&1)g[b][c]|=(1<<i);
			}
		}
	}
	f[0][0]=1;
	for(int i=1;i<=n;i++)
	{
		mem(f[i&1],0);
		for(int b=0;b<(1<<S);b++)
		{
			for(int c=0;c<S;c++)
			{
				f[i&1][g[b][c]]+=f[(i-1)&1][b];
				f[i&1][g[b][c]]%=M;
			}
		}
	}
	int ans=0;
	for(int b=1;b<(1<<S);b++)ans+=f[n&1][b],ans%=M;
	cout<<ans<<endl;

}
AC main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    int _=1;
    //fread;
    //cin>>_;
    while(_--)solve();
    return 0;
}

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

#define rep(i, a, n) for(int i=(a); i<(n); ++i)
#define per(i, a, n) for(int i=(a); i>(n); --i)
#define pb emplace_back
#define mp make_pair
#define clr(a, b) memset(a, b, sizeof(a))
#define all(x) (x).begin(),(x).end()
#define lowbit(x) (x & -x)
#define fi first
#define se second
#define lson o<<1
#define rson o<<1|1
#define gmid l[o]+r[o]>>1

using ll = long long;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll, ll>;
using ui = unsigned int;

constexpr int mod = 998244353;
constexpr int inf = 0x3f3f3f3f;
constexpr double EPS = 1e-8;
const double PI = acos(-1.0);

const int N = 5e4 + 10;

int n, m, dp[N][10];
bool vis[10][10];

inline void add(int &a, int b){
  a += b;
  if(a >= mod)  a -= mod;
}

int main(){
  int x, y;
  scanf("%d %d", &n, &m);
  clr(vis, 0);
  while(m--){
    scanf("%d %d", &x, &y);
    vis[x][y] = vis[y][x] = 1;
  }
  clr(dp, 0);
  rep(i, 0, 10) dp[1][i] = 1;
  rep(i, 1, n){
    rep(j, 0, 10){
      rep(k, 0, 10){
        if(vis[j][k] && j > k)  continue;
        add(dp[i+1][k], dp[i][j]);
      }
    }
  }
  int ans = 0;
  rep(i, 0, 10) add(ans, dp[n][i]);
  printf("%d\n", ans);
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define all(x) x.begin(), x.end()
const int mod = 998244353;
const int iinf = (int)1e9 + 10;
const ll linf = (ll)1e18 + 10;
//-----------------------------------------------------------------------------------------

const int L = 10;
int dp[1<<L][2];
int f[L][L];

void solve(){
	int n, m; cin >> n >> m;
	for (int i = 0; i < m; i++){
		int u, v; cin >> u >> v;
		f[u][v] = f[v][u] = 1;
	}
	for (int i = 0; i <= n; i++){
		int ii = i % 2;
		for (int mask = 0; mask < (1<<L); mask++){
			if (i == 0){
				dp[mask][ii] = 1;
				continue;
			}
			dp[mask][ii] = 0;
			for (int k = 0; k < L; k++){
				int ok = 1;
				for (int l = 0; l < k; l++){
					if (f[l][k] && ((mask>>l)&1)){
						ok = 0;
						break;
					}
				}
				if (ok){
					dp[mask][ii] += dp[(mask - (mask & ((1<<k)-1))) | (1<<k)][ii^1];
					dp[mask][ii] %= mod;
				}
			}
			// cout << i << " " << dp[mask][ii] << endl;
		}
	}
	int ans = dp[0][n%2];
	cout << ans << "\n";
}

int main () {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int t, cnt_t = 0; // cin >> t;
     t = 1;
    while (t--){
        // cnt_t++; cout << "Case #" << cnt_t << ": ";
        solve();
    }

    return 0;
}

// LUOGU_RID: 95282031
#include <bits/stdc++.h>

using namespace std;

using i64=long long;
using u64=unsigned long long;
using db=double;
using pii=pair<int,int>;
using vi=vector<int>;

template<typename T>
inline T read(){
    T x=0,f=0;char ch=getchar();
    while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
    while(isdigit(ch)) x=x*10+(ch-'0'),ch=getchar();
    return f?-x:x;
}

#define rdi read<int>
#define rdi64 read<i64>
#define fi first
#define se second
#define pb push_back

const int D=10,MOD=998244353;

int n,m;
int vis[D][D];
i64 f[2][D][(1<<D)+1];

int main(){
#ifdef LOCAL
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif
    n=rdi(),m=rdi();
    for(int i=1;i<=m;i++){
        int x=rdi(),y=rdi();
        vis[x][y]=vis[y][x]=1;
    }
    for(int i=0;i<D;i++) f[1][i][1<<i]=1;
    i64 ans=0;
    for(int i=1,nw=1;i<=n;i++,nw^=1){
        for(int cur=0;cur<=9;cur++){
            for(int s=1<<cur;s<(1<<(cur+1));s++){
                i64 &val=f[nw][cur][s];
                if(!val) continue;
                val%=MOD;
                if(i<n){
                    for(int to=0;to<=9;to++){
                        if(vis[cur][to]&&(s>>(to+1))) continue;
                        int nxt_s=(vis[cur][to]?s:0)|(1<<to);
                        f[nw^1][to][nxt_s]+=val;
                    }
                }
                else ans+=val;
                val=0;
            }
        }
    }
    ans%=MOD;
    cout<<ans<<endl;
    return 0;
}

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<bitset>
#include<vector>
#include<map>
using namespace std;
#define re int
inline int read(){
	int x=0,ff=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}
	return x*ff;
}
const int mn=998244353;
inline int fs(int x){return x&-x;}
int tot,n,m,f[500005],p[15],q[15];
bool c[10][10];
vector<int>d[15];
int ikt(int k,int m){
	bitset<11>qwq;qwq.reset();
	int x=0;qwq[0]=1;
	for(re i=1;i<=m;i++){
		int u=k/p[m-i],v=0;
		while(qwq[v])v++;
		while(u){
			if(!qwq[v])u--;
			v++;
		}
		k%=p[m-i];
		x+=q[i-1]*(v-1);qwq[v]=1;
	}
	return x;
}
int kt(int k,int m){
	bitset<11>qwq;qwq.reset();int x=0;
	return x;
}
int a[15];
map<int,bool>qwq;
void dfs(int i,int k){
	int x,y,u=i,z=1,v;qwq[i]=1;
	for(re j=0;j<k;j++){
		x=u%10;u/=10;y=u%10;
		if(!c[a[x]][a[y]])continue;
		v=i-z*x-z*10*y+z*x*10+z*y;
		z*=10;
		if(qwq[v])continue;
		dfs(v,k);
	}
}
int main(){
	n=read();p[0]=1;q[0]=1;for(re i=1;i<10;i++)p[i]=p[i-1]*i,q[i]=q[i-1]*10;
	m=read();int x,y;
	for(re i=1;i<=m;i++)x=read(),y=read(),c[x][y]=c[y][x]=1;
	for(re i=1;i<1024;i++){
		x=i;y=0;while(x)y++,x-=fs(x);
		d[y].push_back(i);
	}
	f[0]=1;int ans=0;
	for(re i=1;i<=10&&i<=n;i++){y=0;
		for(re j=1;j<=n;j++)f[j]=(f[j]+f[j-1])%mn;
		for(re j=0;j<d[i].size();j++){
			x=d[i][j];
			memset(a,0,sizeof(a));int z=0;
			for(re r=0;r<10;r++)if((1<<r)&x)a[z++]=r;
			for(re l=0;l<p[i];l++){
				//if(i==4)cout<<l<<" "<<ikt(l,i)<<endl;
				if(qwq[ikt(l,i)])continue;
				y++;dfs(ikt(l,i),i);
			}
			qwq.clear();
		}
		ans=(ans+1ll*y*f[n-i]%mn)%mn;
	}
	cout<<ans<<endl;
	return 0;
}

//太阳出来我晒太阳，月亮出来我晒月亮咯~
//大丘丘病了，二丘丘瞧。三丘丘采药，四丘丘┗|｀O′|┛ 嗷~~.
//If I can't Accept this problem in ten times.Rice_porridge will wear Lolita.
//🥬➡🥬🥬🥬🥬🥬，👴❓👐
//发扬类人智慧

#include<bits/stdc++.h>
#define int long long
#define fep(i,l,r) for(int i=l;i<=r;i++)
#define defep(i,r,l) for(int i=r;i>=l;i--)
#define lep(i,l,r,len) for(int i=l;i<=r;i+=len)
#define delep(i,r,l,len) for(int i=r;i>=l;i-=len)
#define fov(i,v) for(auto i:v)
#define fst first
#define scd second
#define lowbit(x) ((x)&(-x))
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define min4(a,b,c,d) min(a,min(b,min(c,d)))
#define max4(a,b,c,d) max(a,max(b,max(c,d)))
#define min5(a,b,c,d,e) min(a,min(b,min(c,min(d,e))))
#define max5(a,b,c,d,e) max(a,max(b,max(c,max(d,e))))
#define pi pair<int,int>
#define pii pair<pair<int,int>,int>
#define piii pair<pair<pair<int,int>,int>,int>
#define pb(a) push_back(a)
#define sqt(x) (int)(floor(sqrt((long double) x + 1e-16)) )
#define sqr(x) ((x)*(x))
#define zjkakioi(x) ios::sync_with_stdio(x)
using namespace std;
//吾日三省吾身：你清多测了吗？你数组开够了吗？你访问越界了吗？
const int N=5e4+123;
const int M=55;
const int mod=998244353;

int n,m;
int x[M],y[M],f[2][1<<10],can[10][10],to[1<<10][10];

signed main(){
    zjkakioi(0);
    cin>>n>>m;
    fep(i,1,m)cin>>x[i]>>y[i],can[x[i]][y[i]]=can[y[i]][x[i]]=1;f[0][0]=1;
    fep(sta,0,(1<<10)-1){
        fep(i,0,9){
            if(sta&(1<<i)){to[sta][i]=-1;continue;}
            fep(j,0,9){if(!can[i][j])continue;if(j>i||sta&(1<<j))to[sta][i]|=1<<j;}
        }
    }
    int p=0;
    f[0][0]=1;
    fep(i,1,n){
        fep(sta,0,(1<<10)-1){
            if(!f[p][sta])continue;
            cout<<f[p][sta]<<" ";
            fep(j,0,9){int v=to[sta][j];if(v!=-1){(f[p^1][v]+=f[p][sta])%=mod;}}
            f[p][sta]=0;
        }p^=1;
    }
    int ans=0;
    fep(sta,0,(1<<10)-1)(ans+=f[p][sta])%=mod;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
typedef double db;
const int maxn=5e4+5;
const ll mod=998244353;
const double eps=1e-10;
int n,m,ans;
void mul(int &x){
	if(x>=mod)x-=mod;
	else if(x<0)x+=mod;
}
vector<int>e[maxn],to[maxn];
int dp[maxn][1050];
int lowbit(int x){
	return x&(-x);
}
void init(){
	for(int i=0;i<(1<<10);i++){
		if(i)to[i].push_back(i);
		for(int j=0;j<10;j++){
			if((1<<j)&i)continue;
			int flag=0;
			for(auto k:e[j]){
				if((1<<k)&i)flag++;
			}
			if(!flag)to[i].push_back((1<<j));
			else if((!i)||lowbit(i)>(1<<j))to[i].push_back(i^(1<<j));
		}
	}
}
void solve(){
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<(1<<10);j++){
			for(auto k:to[j]){
				dp[i][k]+=dp[i-1][j];
				mul(dp[i][k]);
			}
		}
	}
	for(int i=0;i<(1<<10);i++){
		ans+=dp[n][i];
		mul(ans);
	}
	printf("%d\n",ans);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
	init();
	solve();

	return 0;
}

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using db = long double;
using VS = vector<string>;
using VLL = vector<ll>;
using VVLL = vector<VLL>;
using VVVLL = vector<VVLL>;
using PLL = pair<ll, ll>;
using MLL = map<ll, ll>;
using SLL = set<ll>;
using QLL = queue<ll>;
using SS = stringstream;

#define rep(x, l, u) for (ll x = l; x < u; x++)
#define rrep(x, l, u) for (ll x = l; x >= u; x--)
#define fe(x, a) for (auto x : a)
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define mst(x, v) memset(x, v, sizeof(x))
#define sz(x) (ll) x.size()

#define umap unordered_map
#define uset unordered_set
#define mset multiset

// clang-format off
// --------------------------------- DEBUG ---------------------------------
namespace Debug {
const string open = "[", sep = ", ", close = "]";
struct Second {}; struct First : Second {};

template <typename T>
auto one(T t, First) -> decltype(cerr << t, string()) { stringstream ss; ss << t; return ss.str(); }
template <typename T>
auto one(T t, Second) -> decltype(t.first, t.second, string()) { return open + one(t.first, First()) + ", " + one(t.second, First()) + close; }
template <typename T>
auto one(T t, Second) -> decltype(t.begin(), t.end(), string() ) { string ans = open; for (auto a : t) { ans += (ans == open ? "" : sep) + one(a, First()); } return ans + close; }

string mult() { return ""; }
template <typename A, typename... B>
string mult(A a, B... b) { return one(a, First()) + " " + mult(b...); }
}  // namespace Debug
#ifdef DEBUG
#define debug(...) do { cerr << Debug::mult("[" + string(#__VA_ARGS__) + "]:", __VA_ARGS__) << endl; } while (false)
#else
#define debug(...) do {} while (false)
#endif
// --------------------------------- DEBUG ---------------------------------

ll ob(ll i, ll n) { return i < 0 || i >= n; }
ll tp(ll x) { return ( 1LL << x ); }
ll rup(ll a, ll b) { return a % b ? a/b + 1 : a/b; }
ll sign(ll x) {	return x == 0 ? 0 : x / abs(x); }
VS ssplit(string s) { VS ans; SS ss(s); while (ss >> s) { ans.push_back(s); } return ans; }

void makemod(ll& x, ll m) { x %= m; if (x < 0) { x += m; } }
ll getmod(ll x, ll m) { makemod(x, m); return x; }
ll powmod(ll a, ll b, ll m) { if (b == 0) return 1; ll h = powmod(a, b/2, m); ll ans = h*h%m; return b%2 ? ans*a%m : ans; }
ll invmod(ll a, ll m) { return powmod(a, m - 2, m); }

template<typename A, typename B> void upmin(A& x, B v) { x = min(x, (A)v); }
template<typename A, typename B> void upmax(A& x, B v) { x = max(x, (A)v); }
template<typename A> A reversed(const A& a) { A b = a; reverse(all(b)); return b; }

const VLL di = {0, 0, 1, -1, 1, -1, 1, -1};
const VLL dj = {1, -1, 0, 0, -1, -1, 1, 1};
const ll mod = 998'244'353, mod3 = 1'000'000'207, mod4 = 1'000'003;
const ll inf = (ll)1e18 + 5;
const db eps = 1e-10;
const db pi = acos(0) * 2;

// clang-format on

VVLL E;
ll dp[10][50005];

ll get(ll prev, ll n) {
    if (n == 0) return 1;
    ll& ans = dp[prev][n];
    if (ans != -1) return ans;

    ans = 0;
    rep(cur, 0, 10) {
        if (E[prev][cur] && cur < prev) continue;
        ans += get(cur, n - 1);
        ans %= mod;
    }
    return ans;
}

void solve() {
    mst(dp, -1);

    ll n, m;
    cin >> n >> m;
    E.assign(10, VLL(10, 0));
    rep(i, 0, m) {
        ll a, b;
        cin >> a >> b;
        E[a][b] = 1;
        E[b][a] = 1;
    }

    ll ans = 0;
    rep(i, 0, 10) {
        ans += get(i, n - 1);
        ans %= mod;
    }
    cout << ans << endl;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    ll t = 1;
    // cin >> t;
#ifdef DEBUG
    t = 3;
#endif
    rep(i, 0, t) solve();
    return 0;
}

//author: towrist
#include <iostream>
#include <iomanip>
#include <vector>
#include <functional>
#include <cmath>
#include <algorithm>
#include <set>
#include <utility>
#include <queue>
#include <map>
#include <assert.h>
#include <stack>
#include <climits>
#include <string>
#include <ctime>
#include <chrono>
#include <random>
#define int long long int
using namespace std;

const int mod=998244353;

/*
ok this has to be wrong, cant be this easy.

the size of set of such integers is precisely the number of equivalence classes.

first, sz>= since

every equivalence class has such an integer [and there is no intersection b/w eq classes]

second sz<= since every integer belongs to atleast one eqv class [by definition of
exhaustive set of eq class]

*/

const int D=10;

void solve()
{
	int n, m;
	cin>>n>>m;

	vector<vector<bool>> chk(D, vector<bool>(D, false));
	for (int z=0; z<m; z++)
	{
		int u, v;
		cin>>u>>v;
		assert(u<v);
		chk[u][v]=true;
	}

	vector<vector<int>> dp(n+1, vector<int>(D, 0));

	for (int z=0; z<D; z++) dp[1][z]=1;
	for (int j=2; j<=n; j++)
	{
		for (int i1=0; i1<D; i1++)
		{
			for (int i2=0; i2<D; i2++)
			{
				if (i1>i2)
				{
					if (!chk[i2][i1])
					{
						dp[j][i2]+=dp[j-1][i1];
						if (dp[j][i2]>=mod) dp[j][i2]%=mod;
					}
				}
				else
				{
					dp[j][i2]+=dp[j-1][i1];
					if (dp[j][i2]>=mod) dp[j][i2]%=mod;
				}
			}
		}
	}

	int res=0;
	for (int z=0; z<D; z++) res+=dp[n][z];
	cout<<res%mod<<'\n';

	return;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(NULL); cout.tie(NULL);
	int t;
	//cin >> t;
	t=1;
	cout<<'\n';
	while (t--)
	{
		solve();
	}
	return 0;
}

#include <bits/stdc++.h>

#define f first
#define s second
#define m_p make_pair
#define vec vector
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define sz(x) (int)(x).size()
#define pw(x) (1LL<<(x))
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
template<class T> bool umax(T &a,const T &b){return (a<b?a=b,1:0);}
template<class T> bool umin(T &a,const T &b){return (a>b?a=b,1:0);}

const int M=998244353;
const int K=12;
const int N=5e4+1;

void add(int &a,int b){
    a+=b;
    if(a>=M) a-=M;
    else if(a<0) a+=M;
}
int mult(int a,int b){
    return 1ll*a*b%M;
}
int dp[N][K];

int g[K][K];
signed main(){
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    int m;
    cin>>m;
    vec<pii> e(m);
    for(auto &z : e){
        cin>>z.f>>z.s;
        g[z.f][z.s]=g[z.s][z.f]=1;
    }
    dp[0][10]=1;
//    for(int i=0;i<10;i++)
//        g[10][0]=1;
//    sz[cnt]=1;
//    cout<<"C "<<cnt<<endl;
    for(int i=0;i<n;i++){
        for(int j=0;j<=10;j++){
            for(int k=0;k<10;k++){
                if(!g[j][k] || (k>=j))
                    add(dp[i+1][k],dp[i][j]);
            }
        }
    }
    int ans=0;
    for(int t=0;t<=10;t++){
        add(ans,dp[n][t]);
    }
    cout<<ans;
    return 0;

}
/*
1
4 4
1 2
3 4
1 3
2 4
*/

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

const int maxn = 10;
const int mod = 998244353;

int vis[maxn][maxn],tran[maxn][1<<maxn];
int dp[2][1<<maxn];

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;++i){
		int u,v;
		scanf("%d%d",&u,&v);
		vis[u][v]=vis[v][u]=1;
	}
	for(int i=0;i<maxn;++i){
		for(int j=0;j<(1<<maxn);++j){
			bool ok=true;
			for(int k=0;k<maxn;++k){
				if(!((j>>k)&1) || !vis[k][i])continue;
				if(k<i){
					ok=false;
					break;
				}else{
					tran[i][j]=1<<k;
				}
			}
			if(!ok)tran[i][j]=-1;else{
				tran[i][j]|=1<<i;
			}
		}
	}
	dp[0][0]=1;
	for(int i=1;i<=n;++i){
		int o=!(i&1);
		for(int j=0;j<(1<<maxn);++j){
			for(int k=0;k<maxn;++k){
				if(tran[k][j]==-1)continue;
				dp[i&1][tran[k][j]]+=dp[o][j];
				(dp[i&1][tran[k][j]]>=mod && (dp[i&1][tran[k][j]]-=mod));
			}
		}
		for(int j=(1<<maxn)-1;j>=0;--j){
			dp[o][j]=0;
		}
	}
	int ans=0;
	for(int i=0;i<(1<<maxn);++i){
		ans+=dp[n&1][i];
		(ans>=mod && (ans-=mod));
	}
	printf("%d\n",ans);
}

#include<bits/stdc++.h>
using namespace std;
const int N = 5e4, M = 10, mod = 998244353;
int e[M], dp[N + 5][1 << M];
int main() {
	int n, k, ans = 0;
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= k; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		e[u] |= (1 << v);
		e[v] |= (1 << u);
	}
	for(int i = 0; i < M; i++) {
		dp[1][1 << i] = 1;
	}
	for(int i = 2; i <= n; i++) {
		for(int msk = 1; msk < (1 << M); msk++) {
			for(int j = 0; j < M; j++) {
				int nwmsk = (msk & e[j]) & ((1 << j) - 1);
				if(nwmsk != 0) continue;
				dp[i][nwmsk | (1 << j)] += dp[i - 1][msk] % mod;
			}
		}
	}
	for(int msk = 1; msk < (1 << M); msk++) {
		ans += dp[n][msk] % mod;
	}
	printf("%d", ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
typedef pair<int,int> pii;
#define fi first
#define se second
#define SZ(x) ((int)((x).size()))
#define uid(x,y) uniform_int_distribution<int>(x,y)(rng)
template<class T, class V> void ckmin(T& x, V y) {if (x > y) x = y;}
template<class T, class V> void ckmax(T& x, V y) {if (x < y) x = y;}
template<class T> void pv(T a, T b) {for (T i = a; i != b; i++) cerr << *i << ' '; cerr << '\n';}
void dbg() {cerr << '\n';}
template<class T, class... V> void dbg(T t, V... v) {cerr << t << ' '; dbg(v...);}
template<int modd> struct modint {
    static const int mod = modd;
    int v; explicit operator int() const { return v;}
    modint() : v(0) {}
    modint(ll x) : v(int(x%mod)) {if (v < 0) v += mod;}
    friend bool operator==(const modint& a, const modint& b) {return a.v == b.v;}
    friend bool operator!=(const modint& a, const modint& b) {return a.v != b.v;}
    friend bool operator<(const modint& a, const modint& b) {return a.v < b.v;}
    modint& operator+=(const modint& a) {if ((v += a.v) >= mod) v -= mod; return *this;}
    modint& operator-=(const modint& a) {if ((v -= a.v) < 0) v += mod; return *this;}
    modint& operator*=(const modint& a) {v = int((ll)v*a.v%mod); return *this;}
    modint& operator/=(const modint& a) {return (*this) *= inv(a);}
    friend modint qpow(modint a, ll p) {modint ret = 1; for (; p; p /= 2, a *= a){if (p&1) ret *= a;} return ret;}
    friend modint inv(const modint& a) {return qpow(a,mod-2);}
    modint operator-() const {return modint(-v);}
    modint& operator++() {return *this += 1;}
    modint& operator--() {return *this -= 1;}
    friend modint operator+(modint a, const modint& b) {return a += b;}
    friend modint operator-(modint a, const modint& b) {return a -= b;}
    friend modint operator*(modint a, const modint& b) {return a *= b;}
    friend modint operator/(modint a, const modint& b) {return a /= b;}
    friend ostream& operator<<(ostream& out, modint a) {return out << a.v;}
    friend istream& operator>>(istream& in, modint& a) {ll b; in >> b; a.v = b%mod; return in;}
};
using mint = modint<998244353>;
int adj[10][10];
mint dp[50005][10];
void solve() {
    int n,m;
    cin >> n >> m;
    for (int q = 0; q < m; q++) {
        int a,b;
        cin >> a >> b;
        adj[a][b] = 1;
        adj[b][a] = 1;
    }
    for (int q = 0; q <= 9; q++) dp[1][q] = 1;
    for (int q = 2; q <= n; q++) {
        for (int w = 0; w <= 9; w++) {
            for (int e = w; e <= 9; e++) {
                dp[q][e] += dp[q-1][w];
            }
            for (int e = 0; e < w; e++) {
                if (adj[w][e] == 0) dp[q][e] += dp[q-1][w];
            }
        }
    }
    mint ans = 0;
    for (int q = 0; q <= 9; q++) ans += dp[n][q];
    cout << ans << '\n';
}
int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--) solve();
    return 0;
}

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

const int D = 10;
const int MOD = 998244353;

int N, M;
int adj[D], smaller[D];
int dp[2][1 << D];

void load() {
  scanf("%d%d", &N, &M);
  while (M--) {
    int u, v;
    scanf("%d%d", &u, &v);
    adj[u] |= 1 << v;
    adj[v] |= 1 << u;
    smaller[v] |= 1 << u;
  }
}

inline int add(int x, int y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}

inline void inc(int &x, int y) {
  x = add(x, y);
}

int solve() {
  int* curr = dp[0];
  int* nxt = dp[1];
  curr[0] = 1;
  while (N--) {
    memset(nxt, 0, sizeof nxt);
    for (int i = 0; i < 1 << D; i++)
      for (int j = 0; j < D; j++)
        if (!(i & smaller[j]))
          inc(nxt[(i & adj[j]) | (1 << j)], curr[i]);
    swap(curr, nxt);
  }
  return accumulate(curr, curr + (1 << D), 0, add);
}

int main() {
  load();
  printf("%d\n", solve());
  return 0;
}

#pragma optimize ("Ofast,inline")
#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 7;

int n, m, uv[10][10], dp[50000 + 11][1 << 10];

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	cin >> n >> m;

	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v;
		uv[u][v] = uv[v][u] = true;
	}

	dp[0][0] = 1;

	for (int i = 0; i < n; i++) {
		for (int mask = 0; mask < (1 << 10); mask++) if (dp[i][mask] > 0) {
			for (int j = 0; j < 10; j++) {

				bool ok = true;
				for (int k = 9; k > j; k--) {
					if (uv[j][k] && (mask & (1 << k))) {
						ok = false;
					}
				}

				if (ok) {

					int nxt_mask = 1 << j;

					for (int k = j - 1; k >= 0; k--) if (mask & (1 << k)) {
						if (uv[j][k]) {
							nxt_mask |= 1 << k;
						}
						else {
							break;
						}
					}

					(dp[i + 1][nxt_mask] += dp[i][mask]) %= mod;
				}
			}
		}
	}

	int ans = 0;

	for (int i = 0; i < (1 << 10); i++) {
		(ans += dp[n][i]) %= mod;
	}

	cout << ans << '\n';
}

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

const int S = 10, N = 50002, MOD = 998244353;
int camp[1 << S];
bool conn[S][S];
int dp[2][1 << S];
int trans[1 << S][S];
void solve(int case_t) {
  int n, m;
  cin >> n >> m;
  memset(conn, 0, sizeof(conn));
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    conn[u][v] = conn[v][u] = 1;
  }
  //计算camp

  memset(camp, -1, sizeof(camp));
  for (int mask = 0; mask <= (1 << S); mask++) {
    int minj = 0;
    for (; minj < S; minj++) {
      if (mask & (1 << minj)) break;
    }
    for (int j = minj; j < S; j++) {
      if (!(mask & (1 << j))) continue;
      for (int k = minj; k < S; k++) {
        if (conn[j][k] && (camp[mask] & (1 << k))) {
          camp[mask] ^= 1 << k;
        }
      }
    }
  }

  // 计算trans
  memset(trans, 0, sizeof(trans));
  for (int mask = 0; mask < (1 << S); mask++) {
    for (int c = 0; c < S; c++) {
      trans[mask][c] = 1 << c;
      for (int j = 0; j < S; j++) {
        if ((mask & (1 << j)) && conn[c][j]) {
          trans[mask][c] |= 1 << j;
        }
      }
    }
  }
  // dp
  memset(dp, 0, sizeof(dp));
  int cur = 0;
  dp[0][0] = 1;
  // O(n * S * 2^S)
  for (int i = 0; i < n; i++) {
    memset(dp[cur ^ 1], 0, sizeof(dp[0]));
    for (int mask = 0; mask < (1 << S); mask++) {
      if (dp[cur][mask] == 0) continue;
      for (int c = 0; c < S; c++) {
        if (camp[mask] & (1 << c)) {
          dp[cur ^ 1][trans[mask][c]] = (dp[cur ^ 1][trans[mask][c]] + dp[cur][mask]) % MOD;
        }
      }
    }

    cur ^= 1;
  }

  int ans = 0;
  for (int mask = 1; mask < (1 << S); mask++) {
    //if (dp[cur][mask])
      //cout << mask << " " << dp[cur][mask] << endl;
    ans = (ans + dp[cur][mask]) % MOD;
  }

  printf("%d\n", ans);
}

int main() {
  std::ios::sync_with_stdio(false);
  cin.tie(0); cout.tie(0);

  int t = 1;
  //cin >> t;
  while (t--) {
    solve(t);
  }

}

#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rof(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
const int Maxn=2e5,Maxk=(1<<10)-1,Mod=998244353;

inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

int n,m,ans,vis[10][10];
int chk[Maxk+5][10],num[Maxk+5][10];
int f[2][Maxk+5];

int main()
{
    // freopen("1.in","r",stdin);

    n=read(),m=read();
    For(i,1,m)
    {
        int a=read(),b=read();
        vis[a][b]=vis[b][a]=1;
    }
    For(i,0,Maxk)
    {
        For(j,0,9)
        {
            if(i&(1<<j)) continue;
            chk[i][j]=1;
            int s=0;
            For(k,0,9) if(vis[j][k] && (k>j || i&(1<<j))) s|=(1<<k);
            num[i][j]=s;
        }
    }
    f[0][0]=1;
    For(i,1,n)
    {
        int o=(i&1),p=(o^1);
        memset(f[o],0,sizeof(f[o]));
        For(j,0,Maxk) if(f[p][j])
        {
            int res=f[p][j];
            For(k,0,9) if(chk[j][k])
                f[o][num[j][k]]=(f[o][num[j][k]]+res)%Mod;
        }
    }
    For(j,0,Maxk) ans=(ans+f[n&1][j])%Mod;
    printf("%d\n",ans);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define dbgv(v) cout<<#v<<" = "; f(i,0,v.size()) cout<<v[i]<<" "; cout<<endl
#define dbga(a,x,y) cout<<#a<<" = "; f(i,x,y) cout<<a[i]<<" "; cout<<endl
#define erorp(x) cout<<#x<<"={"<<x.F<<" , "<<x.S<<"}"<<endl
#define eror(x) cout<<#x<<'='<<(x)<<endl
#define f_(i,a,b) for(int i=a;i>=b;i--)
#define f(i,a,b) for(int i=a;i<b;i++)
#define nb(x) __builtin_popcount(x)
#define all(v) v.begin(),v.end()
#define bit(n,k) (((n)>>(k))&1)
#define Add(x,y) x=(x+y)%mod
#define maxm(a,b) a=max(a,b)
#define minm(a,b) a=min(a,b)
#define lst(x) x[x.size()-1]
#define sz(x) int(x.size())
#define mp make_pair
#define ll long long
#define pb push_back
#define S second
#define F first
#define int ll

const int N=1e5+99,mod=998244353;

int n,m,ans,a[N],G[N],dp[2][(1<<10)];

int32_t main(){
	f(i,0,10) f(j,0,10) G[i]|=(1<<j);
	cin>>n>>m;
	f(i,0,m){
		int u,v;
		cin>>u>>v;
		G[u]^=(1<<v);
		G[v]^=(1<<u);
	}
	f(id,0,n){
		int s=id&1;
		dp[s][(1<<10)-2]++;
		f(mask,0,(1<<10)) dp[s^1][mask]=0;
		f(mask,1,(1<<10)){
			int task=mask;
			f_(i,9,0){
				if(bit(task,i+1)) task^=(1<<(i+1));
				if(bit(mask,i)==0) continue ;
				Add(dp[s^1][task|G[i]],dp[s][mask]);
			}
		}
	}
	dp[n&1][0]++;
	f(mask,0,(1<<10)) ans+=dp[n&1][mask];
	cout<<ans;
}

#include <bits/stdc++.h>
using namespace std;
#define REP(I,N) for (I=0;I<N;I++)
#define rREP(I,N) for (I=N-1;I>=0;I--)
#define rep(I,S,N) for (I=S;I<N;I++)
#define rrep(I,S,N) for (I=N-1;I>=S;I--)
#define FOR(I,S,N) for (I=S;I<=N;I++)
#define rFOR(I,S,N) for (I=N;I>=S;I--)

#define DEBUG
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define deputs(str) fprintf(stderr, "%s\n",str)
#else
#define debug(...)
#define deputs(str)
#endif // DEBUG
typedef unsigned long long ULL;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef long long LL;
typedef long long ll;
typedef pair<int,int> pii;
typedef array<int,3> ar3;
typedef array<int,4> ar4;
typedef pair<ll,ll> pll;
const int INF=0x3f3f3f3f;
const LL INFF=0x3f3f3f3f3f3f3f3fll;
const LL M=998244353;
const LL maxn=1e6+107;
const double pi=acos(-1.0);
const double eps=0.0000000001;
LL gcd(LL a, LL b) {return b?gcd(b,a%b):a;}
template<typename T>inline void pr2(T x,int k=64) {ll i; REP(i,k) debug("%d",(x>>i)&1); putchar(' ');}
template<typename T>inline void add_(T &A,int B,ll MOD=M) {A+=B; (A>=MOD) &&(A-=MOD);}
template<typename T>inline void mul_(T &A,ll B,ll MOD=M) {A=(A*B)%MOD;}
template<typename T>inline void mod_(T &A,ll MOD=M) {A%=MOD; A+=MOD; A%=MOD;}
template<typename T>inline void max_(T &A,T B) {(A<B) &&(A=B);}
template<typename T>inline void min_(T &A,T B) {(A>B) &&(A=B);}
template<typename T>inline T abs(T a) {return a>0?a:-a;}
inline ll powMM(ll a, ll b, ll mod=M) {
    ll ret=1;
    for (; b; b>>=1ll,a=a*a%mod)
        if (b&1) ret=ret*a%mod;
    return ret;
}
int startTime;
void startTimer() {startTime=clock();}
void printTimer() {debug("/--- Time: %ld milliseconds ---/\n",clock()-startTime);}

int ban[17][17];
int Ans[50007][18];
int main() {
    int n,m;
    int i,j,k;
    scanf("%d%d",&n,&m);
    FOR(i,1,m) {
        int u,v; scanf("%d%d",&u,&v);
        ban[u][v]=ban[v][u]=1;
    }
    FOR(i,1,n) {
        if (i==1) FOR(j,0,9) Ans[i][j]=1;
        else {
            FOR(j,0,9) FOR(k,0,9) {
                if (k<j&&ban[j][k]) continue;
                add_(Ans[i][k],Ans[i-1][j]);
            }
        }
    }
    int ans=0;
    FOR(j,0,9) add_(ans,Ans[n][j]);
    printf("%d\n",ans);
}
/*
1 4 6 7

5
7 6 1 8 2
*/

#include <bits/stdc++.h>
using namespace std;
typedef long long  ll;
typedef pair<int,int>  ii;

#define ff   first
#define ss   second

const int mod = 998244353;
const int N = 50002;

int dp[N][12];
int sw[12][12];
int n,m;

int go (int i, int d) {
  if (i == n) return 1;
  auto &rf = dp[i][d];
  if (rf!=-1)return rf;
  rf = 0;
  for (int nxt = 0; nxt < 10; ++nxt) {
    if (d <= nxt || !sw[d][nxt])
      rf = (rf + go(i+1, nxt)) % mod;
  }
  return rf;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);cout.tie(0);
  #ifdef LOCAL
  freopen("input.txt","r",stdin);
  #endif // LOCAL
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int u, v; cin >> u >> v;
    sw[u][v]=1;
    sw[v][u]=1;
  }
  memset(dp,-1,sizeof dp);
  cout << go(0,0) << '\n';
}

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cassert>
#include <ctime>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define pb push_back
#define mp make_pair
#define fs first
#define sc second

const int mdl = 998244353;
const int maxn = 50 * 1000 + 100;

int n, m;
int ans[maxn][10];
bool allowed[10][10];

int main() {
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        allowed[u][v] = true;
        allowed[v][u] = true;
    }

    for (int i = 0; i < 10; i++) {
        ans[1][i] = 1;
    }
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 10; j++) {
            for (int k = 0; k < 10; k++) {
                if (!allowed[j][k] || j <= k) {
                    ans[i + 1][k] += ans[i][j];
                    if (ans[i + 1][k] >= mdl) {
                        ans[i + 1][k] -= mdl;
                    }
                }
            }
        }
    }
    int res = 0;
    for (int i = 0; i < 10; i++) {
        res += ans[n][i];
        if (res >= mdl) {
            res -= mdl;
        }
    }

    cout << res << endl;

    return 0;
}

///5od fe genabk deh dohon mohdrga

#pragma GCC optimize("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx,avx2,fma")
using namespace std;

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>

using ll = long long;
using ii = pair<ll, ll>;

#define pb push_back
#define F first
#define S second
#define f(i, a, b)  for(ll i = a; i < b; i++)
#define all(a)  a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define sz(x) (ll)(x).size()
#define mp(x, y) make_pair(x, y)
#define popCnt(x) (__builtin_popcountll(x))
#define LSB(x) (__builtin_ffsll(x) - 1)
#define MSB(x) (64 - __builtin_clzll(x) - 1)
#define int ll

mt19937_64 mrand(chrono::steady_clock::now().time_since_epoch().count());
const int N = 2e5+5, LG = log2(N) + 1, MOD = 998244353;
const double PI = acos(-1);
const int INF = -10000000000;
bool ok[10][10];
int n, m;
int dp[2][1<<10];
bool okMask[10][1<<10];
int go[10][1<<10];
void doWork() {

    cin >> n >> m;
    f(i,0,m) {
        int u, v;
        cin >> u >> v;
        ok[v][u]=true;
        ok[u][v]=true;
    }

    f(i,0,10)f(j,0,1<<10)okMask[i][j]=true;
    for(int digit = 0; digit < 10; digit++) {
        for(int mask = 0; mask < (1 << 10); mask++) {
            for(int j = 0; j < digit; j++) {
                if(mask >> j & 1) {
                    if(ok[j][digit]) {
                        okMask[digit][mask]=false;
                        break;
                    }
                }
            }
            if(okMask[digit][mask]) {
                go[digit][mask]=0;
                for(int j = 0; j < 10; j++)
                if(mask>>j&1) {
                    if(ok[digit][j])
                    go[digit][mask]|=(1 << j);
                }
                go[digit][mask] |= (1 << digit);
            }
        }
    }

    dp[n&1][0] = 1;
    for(int i = n; i >= 1; --i) {
        memset(dp[n&1^1],0,sizeof dp[n&1^1]);
        for(int mask = 0; mask < (1 << 10); mask++) if(dp[i&1][mask]){
            for(int digit = 0; digit < 10; digit++) if(okMask[digit][mask]){
                dp[i&1^1][go[digit][mask]] += dp[i&1][mask];
                if(dp[i&1^1][go[digit][mask]] >= MOD)
                    dp[i&1^1][go[digit][mask]] -= MOD;
            }
        }
    }

    cout << accumulate(dp[0],dp[0]+(1<<10),0ll) % MOD << '\n';

}
int32_t main() {
#ifdef ONLINE_JUDGE
    ios_base::sync_with_stdio(0);
    cin.tie(0);
#endif // ONLINE_JUDGE
    int t = 1;
//    cin >> t;
    while (t--) {
        doWork();
    }
    return 0;
}

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

typedef long long ll;
#define int ll
typedef pair<ll,ll> pi;
typedef vector <ll> vi;
typedef vector <pi> vpi;
typedef pair<pi,ll> pii;
typedef set <ll> si;
typedef long double ld;
#define f first
#define s second
#define FOR(i,s,e) for(ll i=s;i<=ll(e);++i)
#define DEC(i,s,e) for(ll i=s;i>=ll(e);--i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
#define aFOR(i,x) for (auto i: x)
#define mem(x,i) memset(x,i,sizeof x)
#define fast ios_base::sync_with_stdio(false),cin.tie(0)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline ll rand(ll x, ll y) { ++y; return (rng() % (y-x)) + x; } //inclusive
#define INF (ll)1e18
#define maxn 300010
#define MOD 998244353
//~ #define getchar_unlocked _getchar_nolock
int N,M,a,b;
bool adj[10][10];
int dp[maxn][10];

int32_t main(){
    fast;
    cin >> N >> M;
    FOR(i,1,M){
		cin >> a >> b; adj[a][b] = adj[b][a] = 1;
	}

	FOR(j,0,9) dp[0][j] = 1;
	FOR(i,1,N-1) FOR(j,0,9){
		dp[i][j] = 0;
		FOR(k,0,9) if (!adj[k][j] || k <= j){
			if (adj[k][j]) (dp[i][j] += dp[i-1][j]) %= MOD;
			else (dp[i][j] += dp[i-1][k]) %= MOD;
		}
	}
	int ans = 0;
	FOR(j,0,9) (ans += dp[N-1][j]) %= MOD;
	cout << ans;
}

#include<bits/stdc++.h>
#define MOD 998244353
#define root 3
using namespace std;
using ll=long long;
// 特殊な剰余と原始根
// (924844033, 5)
// (998244353, 3)
// (1012924417, 5)
// (167772161, 3)
// (469762049, 3)
// (1224736769, 3)

unsigned int add(const unsigned int x, const unsigned int y)
{
    return (x + y < MOD) ? x + y : x + y - MOD;
}

unsigned int sub(const unsigned int x, const unsigned int y)
{
    return (x >= y) ? (x - y) : (MOD - y + x);
}

unsigned int mul(const unsigned int x, const unsigned int y)
{
    return (unsigned long long)x * y % MOD;
}

unsigned int mod_pow(unsigned int x, unsigned int n)
{
    unsigned int res = 1;
    while(n > 0){
        if(n & 1){ res = mul(res, x); }
        x = mul(x, x);
        n >>= 1;
    }
    return res;
}

unsigned int inverse(const unsigned int x)
{
    return mod_pow(x, MOD - 2);
}

void ntt(vector<ll>& a, const bool rev = false)
{
    unsigned int i, j, k, l, p, q, r, s;
    const unsigned int size = a.size();
    if(size == 1) return;
    vector<ll> b(size);
    r = rev ? (MOD - 1 - (MOD - 1) / size) : (MOD - 1) / size;
    s = mod_pow(root, r);
    vector<unsigned int> kp(size / 2 + 1, 1);
    for(i = 0; i < size / 2; ++i) kp[i + 1] = mul(kp[i], s);
    for(i = 1, l = size / 2; i < size; i <<= 1, l >>= 1){
        for(j = 0, r = 0; j < l; ++j, r += i){
            for(k = 0, s = kp[i * j]; k < i; ++k){
                p = a[k + r], q = a[k + r + size / 2];
                b[k + 2 * r] = add(p, q);
                b[k + 2 * r + i] = mul(sub(p, q), s);
            }
        }
        swap(a, b);
    }
    if(rev){
        s = inverse(size);
        for(i = 0; i < size; i++){ a[i] = mul(a[i], s); }
    }
}

vector<ll> convolute(const vector<ll>& a, const vector<ll>& b)
{
    const ll size = (ll)a.size() + (ll)b.size() - 1;
    ll t = 1;
    while(t < size){ t <<= 1; }
    vector<ll> A(t, 0), B(t, 0);
    for(ll i = 0; i < (ll)a.size(); i++){ A[i] = a[i]; }
    for(ll i = 0; i < (ll)b.size(); i++){ B[i] = b[i]; }
    ntt(A), ntt(B);
    for (ll i = 0; i < t; i++){ A[i] = mul(A[i], B[i]); }
    ntt(A, true);
    A.resize(size);
    return A;
}
ll N,M;
ll U[45];
ll V[45];
using Graph=vector<vector<ll>>;
Graph G(10);
bool Info[10][10];
vector<vector<ll>>dp(10);
vector<ll>sum;
void calcu(){
  vector<ll>X=sum;
  for(ll i=1;i<=16;i++){
    X[0]=1;sum=convolute(sum,X);sum.resize(N+1);
    X[0]=0;X=convolute(X,X);X.resize(N+1);

  }
}
void solve(){
for(ll m=0;m<M;m++)Info[U[m]][V[m]]=true;
for(ll i=0;i<9;i++){
  for(ll j=i+1;j<10;j++)if(!Info[i][j])G[i].push_back(j);
}
for(ll k=0;k<10;k++)dp[k].resize(N+1);
for(ll n=1;n<=N;n++)dp[9][n]=1;

for(ll k=8;0<=k;k--){
sum.resize(0);sum.resize(N+1);
for(auto x:G[k]){
  for(ll n=0;n<N;n++)sum[n+1]=(sum[n+1]+dp[x][n])%MOD;
}sum[1]=1;

calcu();
dp[k]=sum;sum[0]=1;
for(ll l=k+1;l<10;l++){
  dp[l]=convolute(dp[l],sum);dp[l].resize(N+1);
}

}

ll ans=0;for(ll k=0;k<10;k++)ans=(ans+dp[k][N])%MOD;
cout<<ans<<endl;
}
int main(){
cin>>N>>M;
for(ll i=0;i<M;i++)cin>>U[i]>>V[i];
solve();
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (register int i=(a);i<(n);i++)
#define per(i,a,n) for (register int i=(a)-1;i>=(n);i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define SZ(x) (int)x.size()
#define make_unique(x) {sort(all(x)); x.resize(unique(all(x))-x.begin());}
#define bug(x) cerr<<#x<<'='<<x<<' '
#define debug(x) cerr<<#x<<'='<<x<<endl
mt19937 mrand(time(0));
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef double db;
const ll inf=1<<30,mod=998244353;
// head

const int N=1e5+5;
void add(ll &a,ll b) {(a+=b)%=mod;}
int w[10][10];
ll dp[N][10];
int n,m;

int main() {
	scanf("%d%d",&n,&m);
	rep(i,1,m+1) {
		int u,v;
		scanf("%d%d",&u,&v);
		w[u][v]=w[v][u]=1;
	}
	dp[0][0]=1;
	rep(i,0,n) rep(j,0,10) if (dp[i][j]) {
		rep(k,0,10) {
			if (w[j][k]&&k<j) continue;
			add(dp[i+1][k],dp[i][j]);
		}
	}
	ll ans=0;
	rep(i,0,10) add(ans,dp[n][i]);
	printf("%lld\n",ans);

	return 0;
}

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

#define f first
#define s second

typedef long long ll;

const int maxn = 5e4+5;

int edg[10][10];
int dp[maxn][10];
int n, m;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    if(n==1){
        cout << 10;
        return 0;
    }
    while(m--){
        int a, b;
        cin >> a >> b;
        edg[a][b]=1;
    }
    int sum = 0;
    for(int i = 0; i < 10; i++)dp[0][i]=1;
    for(int i = 1; i < n; i++){
        for(int j = 0; j < 10; j++){
            for(int k = 0; k < 10; k++){
                if(!edg[j][k])dp[i][j]+=dp[i-1][k];
            }
            if(i==n-1)sum+=dp[i][j];
        }
    }
    cout << sum;
}

#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast,unroll-loops")

#define ll long long
#define int ll
#define ull unsigned ll
#define ld long double
#define rep(a) rep1(i,a)
#define rep1(i,a) rep2(i,0,a)
#define rep2(i,b,a) for(int i=(b); i<((int)(a)); i++)
#define rep3(i,b,a) for(int i=(b); i>=((int)(a)); i--)
#define chkmin(a,b) (a=min(a,b))
#define chkmax(a,b) (a=max(a,b))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pb push_back
//#define inf 1010000000
#define inf 4000000000000000000
#define eps 1e-9
#define sz(a) ((int)a.size())
#define pow2(x) (1ll<<(x))
#define ceiling(a,b) (((a)+(b)-1)/(b))
#define print0(a) cout << (a) << ' '
#define ykh mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#ifdef i_am_noob
#define bug(...) cerr << "#" << __LINE__ << ' ' << #__VA_ARGS__ << "- ", _do(__VA_ARGS__)
template<typename T> void _do(vector<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(set<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(unordered_set<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(T && x) {cerr << x << endl;}
template<typename T, typename ...S> void _do(T && x, S&&...y) {cerr << x << ", "; _do(y...);}
#else
#define bug(...) 777771449
#endif
template<typename T> void print(T && x) {cout << x << "\n";}
template<typename T, typename... S> void print(T && x, S&&... y) {cout << x << ' ';print(y...);}

const int Mod=1000000007,Mod2=998244353;
const int MOD=Mod2;
template <int mod>
struct Modint{
    int val;
    Modint(int _val=0){val=_val%mod;if(val<0) val+=mod;}
    Modint operator +(const Modint& o) const {
        Modint res;
        res.val=val+o.val;
        if(res.val>=mod) res.val-=mod;
        return res;
    }
    Modint operator +(const int& o) const {return Modint(val+o);}
    Modint operator -() const {
        Modint res;
        res.val=-val;
        if(res.val<0) res.val+=mod;
        return res;
    }
    Modint operator -(const Modint& o) const {
        Modint res;
        res.val=val-o.val;
        if(res.val<0) res.val+=mod;
        return res;
    }
    Modint operator -(const int& o) const {return Modint(val-o);}
    Modint operator *(const Modint& o) const {return Modint(val*o.val);}
    Modint operator *(const int& o) const {return Modint(val*(o%mod));}
    Modint operator +=(const Modint& o){*this=(*this)+o;return *this;}
    Modint operator -=(const Modint& o){*this=(*this)-o;return *this;}
    Modint operator *=(const Modint& o){*this=(*this)*o;return *this;}
    Modint Pow(int b) const {
        Modint tmp(val),ret(1);
        while(b){
            if(b&1) ret*=tmp;
            b>>=1;tmp*=tmp;
        }
        return ret;
    }
    Modint Pow(const Modint& a, int b) const {return a.Pow(b);}
    inline Modint inv() const {return (*this).Pow(mod-2);}
    Modint operator /(const Modint& o) const {return *this*o.inv();}
    Modint operator /(const int& o) const {return *this*Modint(o).inv();}
    bool operator ==(const Modint& o) const {return val==o.val;}
};
template<int mod>
ostream& operator << (ostream& o, Modint<mod> x){return o << x.val;}
template<int mod>
Modint<mod> operator +(const int& x, const Modint<mod>& y){return Modint<mod>(x+y.val);}
template<int mod>
Modint<mod> operator -(const int& x, const Modint<mod>& y){return Modint<mod>(x-y.val);}
template<int mod>
Modint<mod> operator *(const int& x, const Modint<mod>& y){return Modint<mod>(x%mod*y.val);}
#define modint Modint<MOD>
vector<modint> inv,fac,invfac;
void init_comb(int N){
    inv.resize(N),fac.resize(N),invfac.resize(N);
    inv[1]=1,fac[0]=1,invfac[0]=1;
    rep2(i,2,N) inv[i]=inv[MOD%i]*(MOD-MOD/i);
    rep2(i,1,N) fac[i]=fac[i-1]*i;
    rep2(i,1,N) invfac[i]=invfac[i-1]*inv[i];
}
inline modint C(int n, int m){return m>n||m<0?modint(0):fac[n]*invfac[m]*invfac[n-m];}
inline modint H(int n, int m){return C(n+m-1,n);}

const int maxn=305,maxm=32,maxk=7777714;

//i_am_noob
//#define wiwihorz
int n,m;
modint dp[maxn][11];
bool good[11][11];

void orzck(){
    cin >> n >> m;
    rep(m){
        int x,y;
        cin >> x >> y;
        good[y][x]=1;
    }
    rep(10) dp[1][i]=1;
    rep2(i,2,n+1) rep1(j,10) rep1(k,10) if(k>=j||!good[j][k]) dp[i][k]+=dp[i-1][j];
    modint res=0;
    rep(10) res+=dp[n][i];
    print(res);
}

signed main(){
    ios_base::sync_with_stdio(0),cin.tie(0);
    // #ifdef i_am_noob
    // freopen("input1.txt","r",stdin);
    // freopen("output1.txt","w",stdout);
    // freopen("output2.txt","w",stderr);
    // #endif
    cout << fixed << setprecision(15);
    int t;
    #ifdef wiwihorz
    cin >> t;
    #else
    t=1;
    #endif
    ld start=clock();
    while(t--) orzck();
    bug((clock()-start)/CLOCKS_PER_SEC);
    return 0;
}

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <bitset>
#include <vector>
#include <stack>
#include <set>
#include <cstdlib>
#include <unordered_map>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define mp make_pair
#define work system
#define lson tr[now].ls
#define rson tr[now].rs
#define pb push_back
#define debug() cout<<"qwq"<<endl
#define mem(i,a) memset(i,a,sizeof(i))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef double db;
typedef long double ldb;
#define i128 __int128
#define pii pair<int,int>
const db eps=1e-10;
const ll INF = (1ll<<31);
const int siev = 1000000+5;
const int inf = 0x3f3f3f3f;
const ll DMAX = 50000 + 100;
const ll MOD = 998244353;
const ll LMOD = 1000000007;
const int hmod = 202010923;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
template<class T> inline void print(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    int a[20];
    int cnt=0;
    do{
        a[++cnt]=x%10;
        x/=10;
    }while(x>0);
    for(int i=cnt;i>=1;i--){
        putchar(a[i]+'0');
    }
    // putchar(' ');
    puts("");
}
template<class T> inline void read(T &x){
    x=0;
    T f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-'){
            f=-1;
        }
        ch=getchar();
    }
    while(ch<='9' && ch>='0'){
        x=x*10+(ch-'0');
        ch=getchar();
    }
    x*=f;
}
int n;
int m;
int a[DMAX],b[DMAX];
int dp[DMAX][1030];
void add(int &a,int b){
    a=(0ll+a+b)%MOD;
}
int main(){
    read(n),read(m);
    int x,y;
    for(int i=1;i<=m;i++){
        read(x),read(y);
        a[x] |= (1<<y);
        b[y] |= (1<<x);
    }

    int S=(1<<10)-1;
    for(int i=0;i<=9;i++){
        dp[n][1<<i]=1;
    }
    for(int i=n;i>=2;i--){
        for(int x=0;x<=S;x++){
            if(!dp[i][x]){
                continue;
            }
            for(int j=0;j<=9;j++){
                if(b[j] & x){
                    continue;
                }
                add(dp[i-1][(x & a[j]) & (1<<j)],dp[i][x]);
            }
        }
    }
    int ans=0;
    for(int x=0;x<=S;x++){
        add(ans,dp[1][x]);
    }
    print(ans);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 998244353;
int main(){
  int n;
  cin >> n;
  int m;
  cin >> m;
  vector<vector<bool>> ok(10, vector<bool>(10, false));
  for (int i = 0; i < m; i++){
    int u, v;
    cin >> u >> v;
    ok[u][v] = true;
    ok[v][u] = true;
  }
  vector<vector<int>> nxt(1 << 10, vector<int>(10));
  for (int i = 0; i < (1 << 10); i++){
    for (int j = 0; j < 10; j++){
      if ((i >> j & 1) == 1){
        nxt[i][j] = i;
        for (int k = 0; k < j; k++){
          if (ok[j][k]){
            nxt[i][j] &= ~(1 << k);
          } else {
            nxt[i][j] |= 1 << k;
          }
        }
      }
    }
  }
  vector<long long> dp(1 << 10, 0);
  dp[(1 << 10) - 1] = 1;
  for (int i = 0; i < n; i++){
    vector<long long> dp2(1 << 10, 0);
    for (int j = 0; j < (1 << 10); j++){
      for (int k = 0; k < 10; k++){
        if ((j >> k & 1) == 1){
          dp2[nxt[j][k]] += dp[j];
          dp2[nxt[j][k]] %= MOD;
        }
      }
    }
    swap(dp, dp2);
  }
  long long ans = 0;
  for (int i = 0; i < (1 << 10); i++){
    ans += dp[i];
  }
  ans %= MOD;
  cout << ans << endl;
}

//author: towrist
#include <iostream>
#include <iomanip>
#include <vector>
#include <functional>
#include <cmath>
#include <algorithm>
#include <set>
#include <utility>
#include <queue>
#include <map>
#include <assert.h>
#include <stack>
#include <climits>
#include <string>
#include <ctime>
#include <chrono>
#include <random>
#define int long long int
using namespace std;

const int mod=998244353;

/*
ok this has to be wrong, cant be this easy.

the size of set of such integers is precisely the number of equivalence classes.

first, sz>= since

every equivalence class has such an integer [and there is no intersection b/w eq classes]

second sz<= since every integer belongs to atleast one eqv class [by definition of
exhaustive set of eq class]

*/

const int D=10;

void solve()
{
	int n, m;
	cin>>n>>m;

	vector<vector<bool>> chk(D, vector<bool>(D, false));
	for (int z=0; z<m; z++)
	{
		int u, v;
		cin>>u>>v;
		assert(u<v);
		chk[u][v]=true;
	}

	vector<vector<int>> dp(n+1, vector<int>(D, 0));

	for (int z=0; z<D; z++) dp[1][z]=1;
	for (int j=2; j<=n; j++)
	{
		for (int i1=0; i1<D; i1++)
		{
			for (int i2=0; i2<D; i2++)
			{
				if (i1>i2)
				{
					if (!chk[i2][i1])
					{
						dp[j][i2]+=dp[j-1][i1];
						if (dp[j][i2]>=mod) dp[j][i2]%=mod;
					}
				}
				else
				{
					dp[j][i2]+=dp[j-1][i1];
					if (dp[j][i2]>=mod) dp[j][i2]%=mod;
				}
			}
		}
	}

	int res=0;
	for (int z=0; z<D; z++) res+=dp[n][z];
	cout<<res%mod<<'\n';

	return;
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(NULL); cout.tie(NULL);
	int t;
	//cin >> t;
	t=1;
	cout<<'\n';
	while (t--)
	{
		solve();
	}
	return 0;
}

// LUOGU_RID: 94417596
#include<bits/stdc++.h>
using namespace std;using ll=long long;const int N=5e4+10,M=10,K=1<<10,mod=998244353;
int n,m,ans,a[M][M],tr[K][M],f[N][K];
int main(){
	cin>>n>>m;for(int u,v;m--;)cin>>u>>v,a[u][v]=a[v][u]=1;
	for(int i=0;i<K;i++){
		for(int j=0;j<10;j++){
			bool flag=1;
			for(int k=j+1;k<10;k++)if((i>>k&1)&&a[j][k]){flag=0;break;}
			if(!flag)continue;
			int t=0;
			for(int k=0;k<10;k++)if(j==k)t|=1<<k;else if((i>>k&1)&&a[k][j])t|=1<<k;
			tr[i][j]=t;
		}
	}
	f[0][0]=1;
	for(int i=0;i<n;i++)
		for(int j=0;j<K;f[i][j]%=mod,j++)
			if(f[i][j])
				for(int k=0;k<10;k++)
					if(tr[j][k])
						f[i+1][tr[j][k]]+=f[i][j];
	for(int i=0;i<K;i++)(ans+=f[n][i]%mod)%=mod;
	cout<<ans;
	return 0;
}

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

namespace R = ranges;
auto ra(auto x, auto y) { return R::iota_view(x, y); }

using ll = long long;
using ull = long unsigned long;
using ld = double long;

template<int m>
struct modint {
    unsigned x;

    modint() : x(0) {}
    modint(long long arg) : x((arg %= m) < 0 ? arg + m : arg) {}

    modint operator+ (const modint& b) const {
        auto t = *this; t.x = (t.x += b.x) >= m ? t.x-m : t.x; return t;
    }

    modint operator- (const modint& b) const {
        auto t = *this; t.x = (t.x += m-b.x) >= m ? t.x-m : t.x; return t;
    }

    modint operator* (const modint& b) const {
        auto t = *this; t.x = ll(t.x) * b.x % m; return t;
    }

    modint operator/ (const modint& b) const {
        return *this * b.inv();
    }

    modint operator-() const {
        auto t = *this; t.x = x ? m-x : 0; return t;
    }

    template<class T> modint operator^ (T n) const {
        modint t;
        if (n == 0) return t.x = 1, t;
        if (n == 1) return t.x = x, t;
        t = *this ^ (n >> 1); t *= t;
        return n & 1 ? *this * t : t;
    }

    modint& operator+= (const modint& b) { return *this = *this + b; }
    modint& operator-= (const modint& b) { return *this = *this - b; }
    modint& operator*= (const modint& b) { return *this = *this * b; }
    modint& operator/= (const modint& b) { return *this = *this / b; }
    modint& operator++ () { if (++x == m) x = 0; return *this; }
    modint& operator-- () { if (x-- == 0) x = m-1; return *this; }
    modint operator++ (int) { modint tmp = *this; ++*this; return tmp; }
    modint operator-- (int) { modint tmp = *this; --*this; return tmp; }
    bool operator== (const modint& other) const { return x == other.x; }
    bool operator!= (const modint& other) const { return x != other.x; }
    int operator() () const { return x; }
    template<class T> modint operator^= (T n) { return *this = *this ^ n; }
    modint inv() const { return *this ^ (m-2); }
};

const int mod = 1000 * 1000 * 1000 + 7;
typedef modint<mod> mint;

int can[512][10];
bool g[10][10]; // allowed swaps
int n;

void rdi() {
    cin >> n;

    int m;
    cin >> m;
    for (int i : ra(0, m)) {
        int x, y;
        cin >> x >> y;
        g[x][y] = 1;
        g[y][x] = 1;
    }
}

void pcp() {
    // mask[x] = 1 means x cannot be placed
    // to be more precise, the sequence ends with numbers, all swappable with x
    // such that one of them is greater than x

    for (int mask : ra(0, 512)) {
        for (int x : ra(0, 10)) {
            // can we place x?
            if (mask & (1 << x)) {
                can[mask][x] = -1;
                continue;
            }

            // what is the resulting mask?
            // can we place y after x?
            int mask2 = 0;
            for (int y : ra(0, 9)) {
                bool block;
                if (g[x][y]) {
                    block = (mask & (1 << y)) || (x > y);
                } else {
                    block = false;
                }

                if (block) {
                    mask2 |= 1 << y;
                }
            }

            can[mask][x] = mask2;
        }
    }
}

mint d[2][512];

int main() {
    ios::sync_with_stdio(!cin.tie(0));

    rdi();
    pcp();
    d[0][0] = 1;

    for (int i : ra(0, n)) {
        auto ol = d[i%2];
        auto nu = d[(i+1)%2];
        fill(nu, nu+512, mint{});

        for (int mask : ra(0, 512)) {
            for (int x : ra(0, 10)) {
                if (can[mask][x] != -1) {
                    nu[can[mask][x]] += ol[mask];
                }
            }
        }
    }

    cout << accumulate(d[n%2], d[n%2] + 512, mint{})() << '\n';
}

#include<bits/stdc++.h>
using namespace std;
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
#define pb push_back
#define ppb pop_back
#define pf push_front
#define ppf pop_front
#define eb emplace_back
#define ef emplace_front
#define lowbit(x) (x & (-x))
#define ti chrono::system_clock::now().time_since_epoch().count()
#define Fin(x) freopen(x, "r", stdin)
#define Fout(x) freopen(x, "w", stdout)
#define Fio(x) Fin(x".in"), Fout(x".out");
// #define SGT
// #define int long long // int main() -> signed
// #define PAIR
#define ll long long
#ifdef PAIR
#define fi first
#define se second
#endif
#ifdef SGT
#define lson (p << 1)
#define rson (p << 1 | 1)
#define mid ((l + r) >> 1)
#endif
template<int P>
class mod_int{
    using Z=mod_int;
private:
    static int mo(int x){return x<0?x+P:x;}
public:
    int x;
    int val()const{return x;}
    mod_int():x(0){}
    template<class T>mod_int(const T&x_):x(x_>=0&&x_<P?static_cast<int>(x_):mo(static_cast<int>(x_%P))){}
    bool operator==(const Z&rhs)const{return x==rhs.x;}
    bool operator!=(const Z&rhs)const{return x!=rhs.x;}
    Z operator-()const{return Z(x?P-x:0);}
    Z pow(long long k)const{Z res=1,t=*this;while(k){if(k&1)res*=t;if(k>>=1)t*=t;}return res;}
    Z&operator++(){x<P-1?++x:x=0;return *this;}
    Z&operator--(){x?--x:x=P-1;return *this;}
    Z operator++(int){Z ret=x;x<P-1?++x:x=0;return ret;}
    Z operator--(int){Z ret=x;x?--x:x=P-1;return ret;}
    Z inv()const{return pow(P-2);}
    Z&operator+=(const Z&rhs){(x+=rhs.x)>=P&&(x-=P);return *this;}
    Z&operator-=(const Z&rhs){(x-=rhs.x)<0&&(x+=P);return *this;}
    Z&operator*=(const Z&rhs){x=1ULL*x*rhs.x%P;return *this;}
    Z&operator/=(const Z&rhs){return *this*=rhs.inv();}
#define setO(T,o) friend T operator o(const Z&lhs,const Z&rhs){Z res=lhs;return res o##=rhs;}
    setO(Z,+)setO(Z,-)setO(Z,*)setO(Z,/)
#undef setO
};
const int P = 998244353;
using Z = mod_int<P>;
const int maxn = 5e4 + 10, maxk = (1 << 10) + 10;
int n, m, nxt[maxk][maxn];
bool a[11][11];
Z dp[2][maxk], ans;
signed main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++){
        int x, y; scanf("%d%d", &x, &y);
        a[x][y] = a[y][x] = 1;
    }
    memset(nxt, -1, sizeof(nxt));
    for(int i = 0; i < (1 << 10); i++) for(int j = 0; j < 10; j++) if(!(i & (1 << j))){
        nxt[i][j] = i;
        for(int k = 0; k < 10; k++) if((k > j || (i & (1 << k))) && a[j][k]) nxt[i][j] |= (1 << k);
        // printf("nxt %d %d = %d\n", i, j, nxt[i][j]);
    }
    dp[0][0] = 1; int cur = 1;
    for(int i = 1; i <= n; i++, cur ^= 1){
        for(int j = 0; j < (1 << 10); j++) if(dp[cur ^ 1][j].val()){
            for(int k = 0; k < 10; k++) if(~nxt[j][k]) dp[cur][nxt[j][k]] += dp[cur ^ 1][j];
        }
        for(int j = 0; j < (1 << 10); j++) dp[cur ^ 1][j] = 0;
    }
    for(int i = 0; i < (1 << 10); i++) ans += dp[cur ^ 1][i];
    printf("%d\n", ans.val());
    return 0;
}

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

namespace R = ranges;
auto ra(auto x, auto y) { return R::iota_view(x, y); }

using ll = long long;
using ull = long unsigned long;
using ld = double long;

template<int m>
struct modint {
    unsigned x;

    modint() : x(0) {}
    modint(long long arg) : x((arg %= m) < 0 ? arg + m : arg) {}

    modint operator+ (const modint& b) const {
        auto t = *this; t.x = (t.x += b.x) >= m ? t.x-m : t.x; return t;
    }

    modint operator- (const modint& b) const {
        auto t = *this; t.x = (t.x += m-b.x) >= m ? t.x-m : t.x; return t;
    }

    modint operator* (const modint& b) const {
        auto t = *this; t.x = ll(t.x) * b.x % m; return t;
    }

    modint operator/ (const modint& b) const {
        return *this * b.inv();
    }

    template<class T> modint operator^ (T n) const {
        modint t;
        if (n == 0) return t.x = 1, t;
        if (n == 1) return t.x = x, t;
        t = *this ^ (n >> 1); t *= t;
        return n & 1 ? *this * t : t;
    }

    modint& operator+= (const modint& b) { return *this = *this + b; }
    modint& operator-= (const modint& b) { return *this = *this - b; }
    modint& operator*= (const modint& b) { return *this = *this * b; }
    modint& operator/= (const modint& b) { return *this = *this / b; }
    modint& operator++ () { if (++x == m) x = 0; return *this; }
    modint& operator-- () { if (x-- == 0) x = m-1; return *this; }
    modint operator++ (int) { modint tmp = *this; ++*this; return tmp; }
    modint operator-- (int) { modint tmp = *this; --*this; return tmp; }
    bool operator== (const modint& other) const { return x == other.x; }
    bool operator!= (const modint& other) const { return x != other.x; }
    int operator() () const { return x; }
    template<class T> modint operator^= (T n) { return *this = *this ^ n; }
    modint inv() const { return *this ^ (m-2); }
};

const int mod = 998'244'353;
typedef modint<mod> mint;

template<class R>
struct matrix {
    vector<R> a;
    int n, m;

    matrix(int _n, int _m = -1) : n(_n) {
        m = _m == -1 ? n : _m;
        a.resize(n*m);
    }

    static matrix eye(int n) {
        matrix t(n);
        for (int i=0; i<n; i++)
            t[i][i] = 1;
        return t;
    }

    matrix operator* (const matrix& b) const {
        matrix c(n, b.m);
        for (int i=0; i<n; i++)
            for (int j=0; j<m; j++)
                for (int k=0; k<b.m; k++)
                    c[i][k] += a[m*i+j] * b[j][k];
        return c;
    }

    matrix& operator+= (const matrix& b) {
        for (int i=0; i<n*m; i++)
            a[i] += b.a[i];
        return *this;
    }

    matrix& operator-= (const matrix& b) {
        for (int i=0; i<n*m; i++)
            a[i] -= b.a[i];
        return *this;
    }

    matrix operator- () const {
        matrix b(n, m);
        for (int i=0; i<n*m; i++)
            b.a[i] = -a[i];
        return b;
    }

    R* operator[] (int x) { return a.data() + m*x; }
    const R* operator[] (int x) const { return a.data() + m*x; }
    matrix operator+ (const matrix& b) const { auto t = *this; t += b; return t; }
    matrix operator- (const matrix& b) const { auto t = *this; t -= b; return t; }
    matrix& operator*= (const matrix& b) { return *this = *this * b; }
    template<class U> matrix operator^= (U arg) { return *this = *this ^ arg; }

    template<class U>
    matrix operator^ (U arg) const {
        if (arg == 0)
            return matrix::eye(n);
        if (arg == 1)
            return *this;
        auto t = *this ^ (arg >> 1);
        t *= t;
        if (arg & 1)
            t *= *this;
        return t;
    }

    matrix T() const {
        matrix b(m, n);
        for (int i=0; i<n; i++)
            for (int j=0; j<m; j++)
                b[j][i] = a[i][j];
        return b;
    }
};

int main() {
    ios::sync_with_stdio(!cin.tie(0));

    int n;
    cin >> n;

    matrix<mint> a(10, 10);

    R::fill(a.a, 1);

    int m;
    cin >> m;
    while (m--) {
        int x, y;
        cin >> x >> y;
        if (x > y) swap(x, y);
        a[y][x] = 0;
    }

    a ^= n-1;
    cout << accumulate(begin(a.a), end(a.a), mint{})() << '\n';
}

#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
#include <string>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <random>
#include <chrono>
#define all(v) (v).begin(), (v).end()
#define unq(v) (v).erase(unique(all(v)), (v).end())
#define sz(v) ((int)(v).size())
#define pii pair <int, int>
#define pli pair <ll, int>
#define pil pair <int, ll>
#define pll pair <ll, ll>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define MULTI int _T; cin >> _T; while(_T--)
#define sqr(x) ((x) * (x))
#define yesno(x) cout << ((x) ? "Yes" : "No") << endl
#define test cerr << '!' << endl;
using namespace std;

typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;

void main0 ();
int main () {
	clock_t start, end;
	#ifndef ONLINE_JUDGE
		freopen("file.in", "r", stdin);
		start = clock();
	#endif
	ios::sync_with_stdio(false); cin.tie(0);
	main0();
	#ifndef ONLINE_JUDGE
		end = clock();
		cout << "( " << (end - start) << " ms )" << endl;
		fclose(stdin);
	#endif
	return 0;
}

const int dx[8] = {0, 1, -1, 0, 1, 1, -1, -1};
const int dy[8] = {1, 0, 0, -1, 1, -1, -1, 1};
const int N = 5e4 + 5;
const int D = 10;
const int INF = 0x3f3f3f3f;
const ll INFF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-6;
mt19937 rnd((uint) chrono::steady_clock::now().time_since_epoch().count());
template <typename T> bool chkmin (T &x, T y) {return y < x ? x = y, 1 : 0;}
template <typename T> bool chkmax (T &x, T y) {return y > x ? x = y, 1 : 0;}

int n, m;
int a[D][D];

int dp[N][1 << D];
int news[1 << D][D];

void main0 () {
	cin >> n >> m;
	for (int i = 1;i <= m;++i) {
		int u, v;
		cin >> u >> v;
		a[u][v] = a[v][u] = 1;
	}

	int S = (1 << D) - 1;
	for (int s = 0;s <= S;++s) {
		for (int d = 0;d <= D - 1;++d) if (((s >> d) & 1) == 0) {
			for (int newd = 0;newd <= D - 1;++newd) {
				if (a[d][newd] && (d > newd)) news[s][d] |= (1 << newd);
			}
		}
	}

	dp[0][0] = 1;
	for (int i = 1;i <= n;++i) {
		for (int s = 0;s <= S;++s) if (dp[i - 1][s]) {
			for (int d = 0;d <= D - 1;++d) if (((s >> d) & 1) == 0) {
				dp[i][news[s][d]] += dp[i - 1][s];
				dp[i][news[s][d]] %= mod;
			}
		}
	}
	cout << accumulate(dp[n], dp[n] + (1 << D), 0) << endl;
}

#include <bits/stdc++.h>

#define rep(i,l,r) for (int i = l; i <= r; i++)
#define per(i,r,l) for (int i = r; i >= l; i--)
#define fi first
#define se second
#define prt std::cout
#define gin std::cin
#define edl std::endl

namespace wxy{

const int N = 5e4 + 50,mod = 998244353;

typedef long long ll;

bool flag[10][1<<10];

int trans[10][1<<10];

int f[N][1<<10],G[10][10],n,m;

bool check(int t,int S) {
    rep(i,0,9) if ((i < t) && (S >> i & 1) && (G[t][i])) return false;
    return true;
}

inline void main(){
    #ifndef ONLINE_JUDGE
        freopen("in.in","r",stdin);
        freopen("out.out","w",stdout);
    #endif
    gin >> n >> m; rep(i,1,m) {int u,v; gin >> u >> v; G[u][v] = G[v][u] = 1;}
    rep(i,0,9) rep(S,0,(1<<10)-1) flag[i][S] = check(i,S);
    rep(i,0,9) rep(S,0,(1<<10)-1) {
        if (!flag[i][S]) continue;
        rep(k,0,9) if ((S>>k&1)&&(G[i][k])) trans[i][S] |= (1<<k);
    }
    rep(i,0,9) f[1][1<<i] = 1;
    rep(i,1,n-1) rep(S,0,(1<<10)-1) rep(t,0,9) if (flag[t][S])
        f[i+1][trans[t][S]] = (f[i+1][trans[t][S]] + f[i][S]) % mod;
    int res = 0; rep(S,0,(1<<10)-1) res = (res + f[n][S]) % mod;
    prt << res;
}

}signed main(){wxy::main(); return 0;}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

int rand(int l, int r) { return (int) ((ll) rnd() % (r - l + 1)) + l; }

#define mp(x, y) make_pair(x, y)
#define sz(x) (int)size(x)
#define trace(x) cout << #x << ": " << x << endl;
#define all(x) begin(x), end(x)

const int A = 10, N = 50000;
constexpr int mod = 998244353;

int add(int a, int b) {
    return a + b >= mod ? a + b - mod : a + b;
}

int mul(int a, int b) {
    return a * (ll) b % mod;
}

int sub(int a, int b) {
    return a >= b ? a - b : a - b + mod;
}

bool e[A][A];

int dp[A][N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    memset(e, true, sizeof(e));
    for (int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        if (a > b) {
            swap(a, b);
        }
        e[a][b] = false;
    }
    for (int x = 0; x < A; ++x) {
        dp[x][0] = 1;
    }
    for (int i = 1; i < n; ++i) {
        for (int x = 0; x < A; ++x) {
            for (int y = 0; y < A; ++y) {
                if (e[x][y]) {
                    dp[x][i] = add(dp[x][i], dp[y][i - 1]);
                }
            }
        }
    }
    int ans = 0;
    for (int x = 0; x < A; ++x) {
        ans = add(ans, dp[x][n - 1]);
    }
    cout << ans;
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define FORI(i, a, b) for (int (i) = (a); (i) < (b); (i)++)

#define ll long long
#define mp(m, n) make_pair((m), (n))

template<typename T>
void read(vector<T> &t) {FOR(i, t.size()) {cin >> t[i];}}
template<typename T> string tostring(T a) { istringstream sin; sin >> a; return sin.str(); }

// #define DEBUG

#ifdef DEBUG
template<typename T>
void _debug(string s, T x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << *it;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, map<T, K> x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << it->first << ":" << it->second;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, set<T, K> x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << *it;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, vector<pair<T, K> > x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << it->first << "," << it->second;
    }
    cerr << endl;
}

void _debug(string s, int x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, long long x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, double x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, string x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, char x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, size_t x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, bool x) {
    cerr << s << ": " << x << endl;
}

#define debug(x) _debug(#x, (x))
#else
#define debug(x)
#endif

#define db debug

void solve();

void pre_init();

int main() {
    ios_base::sync_with_stdio(false); std::cin.tie(0);
    pre_init();
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
    }
}

void pre_init() {}

long long dp[2][1024];

void solve() {
    int n;
    int m;
    long long mod = 998244353;
    cin >> n >> m;
    vector<vector<long long> > v(10, vector<long long>(10));
    vector<vector<long long> > to(1024);
    FOR(i, m) {
        int a, b;
        cin >> a >> b;
        if (a > b) swap(a, b);
        v[b][a] = v[a][b] = 1;
    }
    cerr << clock() << endl;
    for (int i = 0; i < 1024; i++) {
        for (int j = 0; j < 10; j++) {
            int n_mask = (1 << j);
            bool bad = false;
            for (int k = 0; k < 10; k++) {
                if (((1<<k) & i) && k > j && v[k][j]) bad = true;
                if (((1<<k) & i) && v[k][j]) {
                    n_mask |= (1 << k);
                }
            }
            if (!bad) {
                to[i].push_back(n_mask);
            }
        }
    }
    for (int i = 0; i < 10; i++) dp[0][1<<i] = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 1024; j++) {
            for (int k = 0; k < to[j].size(); k++) {
                dp[i & 1][to[j][k]] += dp[(i & 1) ^ 1][j];
            }
        }
        for (int j = 0; j < 1024; j++) {
            dp[i & 1][j] %= mod;
        }
    }
    long long ans = 0;
    FOR (i, 1024) {
        ans += dp[(n & 1) ^ 1][i];
        ans %= mod;
    }
    cout << ans << endl;
    cerr << clock() << endl;
}

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

const int D = 10;
const int MOD = 998244353;

int N, M;
int adj[D], smaller[D];
int dp[2][1 << D];

void load() {
  scanf("%d%d", &N, &M);
  while (M--) {
    int u, v;
    scanf("%d%d", &u, &v);
    adj[u] |= 1 << v;
    adj[v] |= 1 << u;
    smaller[v] |= 1 << u;
  }
}

inline int add(int x, int y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}

inline void inc(int &x, int y) {
  x = add(x, y);
}

int solve() {
  int* curr = dp[0];
  int* nxt = dp[1];
  curr[0] = 1;
  while (N--) {
    memset(nxt, 0, sizeof nxt);
    for (int i = 0; i < 1 << D; i++)
      for (int j = 0; j < D; j++)
        if (!(i & smaller[j]))
          inc(nxt[(i & adj[j]) | (1 << j)], curr[i]);
    swap(curr, nxt);
  }
  return accumulate(curr, curr + (1 << D), 0, add);
}

int main() {
  load();
  printf("%d\n", solve());
  return 0;
}

#include<bits/stdc++.h>
#define fep(i,l,r) for(int i=l;i<=r;++i)
#define feb(i,r,l) for(int i=r;i>=l;--i)
#define For(i,u) for(int i=head[u];i;i=e[i].nxt)
#define ld long double
#define LL long long
//#define int long long
#define pr pair<int,int>
#define mpr make_pair
using namespace std;

const int N = 1e4+5,M = 10,mod = 1e9+7;
int n,m,f[2][1<<M],mp[M][M],to[1<<M][N];

inline int read()
{
	int s=0,w=1; char ch=getchar();
	while(!(ch>='0'&&ch<='9')) {if(ch=='-') w=-1; ch=getchar();}
	while(  ch>='0'&&ch<='9')  {s=(s<<1)+(s<<3)+ch-'0';; ch=getchar();}
	return s*w;
}
inline int Mod(int x) {return x>=mod?x-mod:x;}
inline void addmod(int &x,int y) {x=Mod(x+y);}

signed main()
{
	n=read(),m=read();
	fep(i,1,m)
	{
		int x=read(),y=read();
		mp[x][y]=mp[y][x]=1;
	}
	fep(S,0,1023)
	{
		fep(i,0,9)
			if((1<<i)&S) to[S][i]=-1;
			else
				fep(j,0,9) if(mp[i][j])
					if(j>i||S&(1<<j)) to[S][i]+=(1<<j);
	}
	int p=0,ans=0; f[0][0]=1;
	fep(T,1,n)
	{
		p^=1;
		fep(S,0,1023)
			fep(i,0,9) if(!((1<<i)&S))
				addmod(f[p][to[S][i]],f[p^1][S]);
		fep(S,0,1023) f[p^1][S]=0;
	}
	fep(S,0,1023) addmod(ans,f[p][S]);
	printf("%d",ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair <int, int> pii;
#define fir first
#define sec second
template <typename __Tp> void read(__Tp &x) {
	int f = x = 0; char ch = getchar();
	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = 1;
	for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	if (f) x = -x;
}
void read(char &ch) { for (ch = getchar(); isspace(ch); ch = getchar()); }
template <typename __Tp1, typename ...__Tp2> void read(__Tp1 &x, __Tp2 &... y) { read(x), read(y...); }
template <typename __Tp> void write(__Tp x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) write(x / 10);
	putchar(x % 10 + 48);
}
void write(char ch) { putchar(ch); }
void write(const char *s) { for (; *s; ++s) putchar(*s); }
template <typename __Tp1, typename ...__Tp2> void write(__Tp1 x, __Tp2 ... y) { write(x), write(y...); }
template <int mod>
class mint {
	public:
		int x;
		mint() : x(0) {}
		mint(int _x) { (x = _x % mod) < 0 ? x += mod : 0; }
		mint(long long _x) { (x = _x % mod) < 0 ? x += mod : 0; }
		mint(unsigned int _x) { (x = _x % mod) < 0 ? x += mod : 0; }
		mint(unsigned long long _x) { (x = _x % mod) < 0 ? x += mod : 0; }
		friend mint operator + (mint a, mint b) { return (a.x += b.x) >= mod ? a.x -= mod : 0, a; }
		friend mint operator - (mint a, mint b) { return (a.x -= b.x) < 0 ? a.x += mod : 0, a; }
		friend mint operator * (mint a, mint b) { return a.x = 1ll * a.x * b.x % mod, a; }
		template <typename __Tp> friend mint operator ^ (mint a, __Tp p) {
			mint ans = 1;
			while (p) {
				if (p & 1) ans = ans * a;
				a = a * a, p >>= 1;
			}
			return ans;
		}
		friend mint operator / (mint a, mint b) { return a * (b ^ (mod - 2)); }
		friend mint & operator += (mint &a, mint b) { return a = a + b; }
		friend mint & operator -= (mint &a, mint b) { return a = a - b; }
		friend mint & operator *= (mint &a, mint b) { return a = a * b; }
		friend mint & operator /= (mint &a, mint b) { return a = a / b; }
		friend mint & operator ^= (mint &a, int b) { return a = a ^ b; }

		mint & operator ++ () { return *this += 1; }
		const mint operator ++ (int) { mint t = *this; *this += 1; return t; }
		mint & operator -- () { return *this -= 1; }
		const mint operator -- (int) { mint t = *this; *this -= 1; return t; }

		friend bool operator == (mint a, mint b) { return a.x == b.x; }
		friend bool operator != (mint a, mint b) { return a.x != b.x; }
};

const int maxn = 50010, mod = 998244353;
typedef mint <mod> mi;
int n, m, a[20][20], nxt[1 << 10][20];
mi f[maxn][1 << 10];

int main() {
	read(n, m);
	for (int i = 1; i <= m; ++i) {
		int u, v; read(u, v);
		a[u][v] = a[v][u] = 1;
	}
	for (int sta = 0; sta < (1 << 10); ++sta) {
		for (int i = 0; i < 10; ++i) {
			nxt[sta][i] = (1 << i);
			for (int j = 0; j < 10; ++j) if ((sta >> j) & 1) {
				if (!a[i][j] || j <= i) nxt[sta][i] |= (1 << j);
				else nxt[sta][i] = -1;
			}
		}
	}
	f[0][0] = 1;
	for (int i = 0; i < n; ++i)
		for (int sta = 0; sta < (1 << 10); ++sta)
			for (int j = 0; j < 10; ++j)
				if (nxt[sta][j] != -1) f[i + 1][nxt[sta][j]] += f[i][sta];
	mi ans = 0;
	for (int sta = 0; sta < (1 << 10); ++sta) ans += f[n][sta];
	write(ans.x, '\n');
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int mod=998244353;
bool nt[10][10];
int dp[50009][10],n,m;
int go(int x,int lst)
{
    if(x==0)return 1;
    if(dp[x][lst]!=-1)return dp[x][lst];
    dp[x][lst]=0;
    for(int i=0;i<10;i++)
    {
        if(i<lst && (nt[i][lst]==true))continue;
        dp[x][lst]+=go(x-1,i);
        dp[x][lst]%=mod;
    }
    return dp[x][lst];
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x,y;
        cin>>x>>y;
        nt[x][y]=nt[y][x]=true;
    }
    memset(dp,-1,sizeof dp);
    cout<<go(n,0);
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define dbgv(v) cout<<#v<<" = "; f(i,0,v.size()) cout<<v[i]<<" "; cout<<endl
#define dbga(a,x,y) cout<<#a<<" = "; f(i,x,y) cout<<a[i]<<" "; cout<<endl
#define erorp(x) cout<<#x<<"={"<<x.F<<" , "<<x.S<<"}"<<endl
#define eror(x) cout<<#x<<'='<<(x)<<endl
#define f_(i,a,b) for(int i=a;i>=b;i--)
#define f(i,a,b) for(int i=a;i<b;i++)
#define nb(x) __builtin_popcount(x)
#define all(v) v.begin(),v.end()
#define bit(n,k) (((n)>>(k))&1)
#define Add(x,y) x=(x+y)%mod
#define maxm(a,b) a=max(a,b)
#define minm(a,b) a=min(a,b)
#define lst(x) x[x.size()-1]
#define sz(x) int(x.size())
#define mp make_pair
#define ll long long
#define pb push_back
#define S second
#define F first
#define int ll

const int N=1e5+99,mod=998244353;

int n,m,ans,a[N],G[N],dp[2][(1<<10)];

int32_t main(){
	f(i,0,10) f(j,0,10) G[i]|=(1<<j);
	cin>>n>>m;
	f(i,0,m){
		int u,v;
		cin>>u>>v;
		G[u]^=(1<<v);
		G[v]^=(1<<u);
	}
	f(id,0,n){
		int s=id&1;
		dp[s][(1<<10)-2]++;
		f(mask,0,(1<<10)) dp[s^1][mask]=0;
		f(mask,1,(1<<10)){
			int task=mask;
			f_(i,9,0){
				if(bit(task,i+1)) task^=(1<<(i+1));
				if(bit(mask,i)==0) continue ;
				Add(dp[s^1][task|G[i]],dp[s][mask]);
			}
		}
	}
	dp[n&1][0]++;
	f(mask,0,(1<<10)) ans+=dp[n&1][mask];
	cout<<ans;
}

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

const int mod = 998244353;
const int Maxn = 50005;
const int Maxd = 10;

int n;
int m;
bool E[Maxd][Maxd];
bool good[1 << Maxd][Maxd];
int nxt[1 << Maxd][Maxd];
int cur, dp[2][1 << Maxd];

int main()
{
    scanf("%d", &n);
    scanf("%d", &m);
    for (int i = 0; i < Maxd; i++)
        E[i][i] = true;
    for (int i = 0; i < m; i++) {
        int a, b; scanf("%d %d", &a, &b);
        E[a][b] = E[b][a] = true;
    }
    for (int i = 0; i < 1 << Maxd; i++)
        for (int j = 0; j < Maxd; j++) {
            bool fall = false;
            for (int k = 0; k < Maxd; k++) if (i & 1 << k)
                if (!E[j][k]) break;
                else if (k > j) { fall = true; break; }
            good[i][j] = !fall;
            int ni = i;
            for (int k = 0; k < j; k++) if (ni & 1 << k)
                ni ^= 1 << k;
            ni |= 1 << j;
            nxt[i][j] = ni;
        }
    dp[cur][0] = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 1 << Maxd; j++) if (dp[cur][j]) {
            int ways = dp[cur][j]; dp[cur][j] = 0;
            for (int k = 0; k < Maxd; k++) if (good[j][k])
                dp[!cur][nxt[j][k]] = (dp[!cur][nxt[j][k]] + ways) % mod;
        }
        cur = !cur;
    }
    int res = 0;
    for (int j = 0; j < 1 << Maxd; j++)
        res = (res + dp[cur][j]) % mod;
    printf("%d\n", res);
    return 0;
}

// LUOGU_RID: 94495355
#include <cstdio>
#include <algorithm>
using namespace std;
int read(){
	char c=getchar();int x=0;
	while(c<48||c>57) c=getchar();
	do x=(x<<1)+(x<<3)+(c^48),c=getchar();
	while(c>=48&&c<=57);
	return x;
}
const int N=50003,P=998244353;
int f[N][10];
int n,m;
bool g[10][10];
void inc(int &x,int v){if((x+=v)>=P) x-=P;}
int main(){
	n=read();m=read();
	for(int i=1;i<=m;++i){
		int u=read(),v=read();
		if(u<v) g[v][u]=1;
		else g[u][v]=1;
	}
	for(int i=0;i<10;++i) f[1][i]=1;
	for(int i=1;i<n;++i)
		for(int j=0;j<10;++j)
			for(int k=0;k<10;++k){
				if(g[j][k]) continue;
				inc(f[i+1][k],f[i][j]);
			}
	int res=0;
	for(int i=0;i<10;++i) inc(res,f[n][i]);
	printf("%d\n",res);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;
#define int long long
const int p=998244353;
const int maxn=5e4+5;
bool ok[10][10];
int dp[maxn][10];
int32_t main()
{
    ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    for(int i=0;i<10;++i) for(int j=0;j<10;++j) ok[i][j]=true;
    int n;cin>>n;
    int m;cin>>m;for(int i=0;i<m;++i) {int x,y;cin>>x>>y;ok[x][y]=false;ok[y][x]=false;}
    for(int i=0;i<10;++i) dp[1][i]=1;
    for(int i=1;i<n;++i)
    {
        for(int j=0;j<10;++j)
        {
            for(int k=0;k<10;++k)
            {
                if(j==k) {dp[i+1][k]+=dp[i][j];dp[i+1][k]%=p;continue;}
                if(j>k) {dp[i+1][k]+=dp[i][j];dp[i+1][k]%=p;continue;}
                if(ok[j][k]) {dp[i+1][k]+=dp[i][j];dp[i+1][k]%=p;continue;}
            }
        }
    }
    int ans=0;for(int i=0;i<10;++i) {ans+=dp[n][i];ans%=p;}
    cout<<ans;
    return 0;
}

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

typedef long long ll;
typedef pair<ll,ll> pi;
typedef vector <ll> vi;
typedef vector <pi> vpi;
typedef pair<pi,ll> pii;
typedef set <ll> si;
typedef long double ld;
#define f first
#define s second
#define FOR(i,s,e) for(int i=s;i<=int(e);++i)
#define DEC(i,s,e) for(int i=s;i>=int(e);--i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define lbd(x, y) lower_bound(all(x), y)
#define ubd(x, y) upper_bound(all(x), y)
#define aFOR(i,x) for (auto i: x)
#define mem(x,i) memset(x,i,sizeof x)
#define fast ios_base::sync_with_stdio(false),cin.tie(0)
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());    //can be used by calling rng() or shuffle(A, A+n, rng)
inline ll rand(ll x, ll y) { ++y; return (rng() % (y-x)) + x; } //inclusive
#define INF (ll)1e18
#define maxn 50001
#define MOD 998244353
//~ #define getchar_unlocked _getchar_nolock
int N,M,a,b;
int adj[10];
ll dp[2][1024];
int msk[10];
int newmsk[1024][10];
bool ok[1024][10];

int32_t main(){
    fast;
    cin >> N >> M;
    FOR(i,0,9) adj[i] = (1<<i);
    FOR(i,1,M){
		cin >> a >> b; adj[a] |= (1<<b);
		//~ adj[b] |= (1<<a);
	}
	FOR(i,0,9) msk[i] = 1023 ^ ((1<<(i+1))-1);
	FOR(i,0,1023) FOR(j,0,9){
		newmsk[i][j] = (i&adj[j]) | (1<<j);
		ok[i][j] = ((newmsk[i][j] & msk[j]) == 0);
	}
	FOR(j,0,(1<<10)-1) dp[0][j] = 1;
	FOR(i,1,N) FOR(j,0,1023){
		dp[i&1][j] = 0;
		FOR(k,0,9){
			// check if there is an a > k set in j & adj[k]
			if (ok[j][k]){
				dp[i&1][j] += (dp[!(i&1)][newmsk[j][k]]) %= MOD;
			}
		}
	}
	cout << dp[N%2][0];
}

#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast,unroll-loops")

#define ll long long
#define int ll
#define ull unsigned ll
#define ld long double
#define rep(a) rep1(i,a)
#define rep1(i,a) rep2(i,0,a)
#define rep2(i,b,a) for(int i=(b); i<((int)(a)); i++)
#define rep3(i,b,a) for(int i=(b); i>=((int)(a)); i--)
#define chkmin(a,b) (a=min(a,b))
#define chkmax(a,b) (a=max(a,b))
#define all(a) a.begin(),a.end()
#define pii pair<int,int>
#define pb push_back
//#define inf 1010000000
#define inf 4000000000000000000
#define eps 1e-9
#define sz(a) ((int)a.size())
#define pow2(x) (1ll<<(x))
#define ceiling(a,b) (((a)+(b)-1)/(b))
#define print0(a) cout << (a) << ' '
#define ykh mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#ifdef i_am_noob
#define bug(...) cerr << "#" << __LINE__ << ' ' << #__VA_ARGS__ << "- ", _do(__VA_ARGS__)
template<typename T> void _do(vector<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(set<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(unordered_set<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(T && x) {cerr << x << endl;}
template<typename T, typename ...S> void _do(T && x, S&&...y) {cerr << x << ", "; _do(y...);}
#else
#define bug(...) 777771449
#endif
template<typename T> void print(T && x) {cout << x << "\n";}
template<typename T, typename... S> void print(T && x, S&&... y) {cout << x << ' ';print(y...);}

const int Mod=1000000007,Mod2=998244353;
const int MOD=Mod2;
template <int mod>
struct Modint{
    int val;
    Modint(int _val=0){val=_val%mod;if(val<0) val+=mod;}
    Modint operator +(const Modint& o) const {
        Modint res;
        res.val=val+o.val;
        if(res.val>=mod) res.val-=mod;
        return res;
    }
    Modint operator +(const int& o) const {return Modint(val+o);}
    Modint operator -() const {
        Modint res;
        res.val=-val;
        if(res.val<0) res.val+=mod;
        return res;
    }
    Modint operator -(const Modint& o) const {
        Modint res;
        res.val=val-o.val;
        if(res.val<0) res.val+=mod;
        return res;
    }
    Modint operator -(const int& o) const {return Modint(val-o);}
    Modint operator *(const Modint& o) const {return Modint(val*o.val);}
    Modint operator *(const int& o) const {return Modint(val*(o%mod));}
    Modint operator +=(const Modint& o){*this=(*this)+o;return *this;}
    Modint operator -=(const Modint& o){*this=(*this)-o;return *this;}
    Modint operator *=(const Modint& o){*this=(*this)*o;return *this;}
    Modint Pow(int b) const {
        Modint tmp(val),ret(1);
        while(b){
            if(b&1) ret*=tmp;
            b>>=1;tmp*=tmp;
        }
        return ret;
    }
    Modint Pow(const Modint& a, int b) const {return a.Pow(b);}
    inline Modint inv() const {return (*this).Pow(mod-2);}
    Modint operator /(const Modint& o) const {return *this*o.inv();}
    Modint operator /(const int& o) const {return *this*Modint(o).inv();}
    bool operator ==(const Modint& o) const {return val==o.val;}
};
template<int mod>
ostream& operator << (ostream& o, Modint<mod> x){return o << x.val;}
template<int mod>
Modint<mod> operator +(const int& x, const Modint<mod>& y){return Modint<mod>(x+y.val);}
template<int mod>
Modint<mod> operator -(const int& x, const Modint<mod>& y){return Modint<mod>(x-y.val);}
template<int mod>
Modint<mod> operator *(const int& x, const Modint<mod>& y){return Modint<mod>(x%mod*y.val);}
#define modint Modint<MOD>
vector<modint> inv,fac,invfac;
void init_comb(int N){
    inv.resize(N),fac.resize(N),invfac.resize(N);
    inv[1]=1,fac[0]=1,invfac[0]=1;
    rep2(i,2,N) inv[i]=inv[MOD%i]*(MOD-MOD/i);
    rep2(i,1,N) fac[i]=fac[i-1]*i;
    rep2(i,1,N) invfac[i]=invfac[i-1]*inv[i];
}
inline modint C(int n, int m){return m>n||m<0?modint(0):fac[n]*invfac[m]*invfac[n-m];}
inline modint H(int n, int m){return C(n+m-1,n);}

const int maxn=50005,maxm=32,maxk=7777714;

//i_am_noob
//#define wiwihorz
int n,m,good[11];
modint dp[pow2(10)+5],ndp[pow2(10)+5];

void orzck(){
    cin >> n >> m;
    rep(10) good[i]=1023;
    rep(m){
        int x,y;
        cin >> x >> y;
        good[y]&=~pow2(x);
    }
    rep(10) dp[pow2(i)]=1;
    rep2(i,2,n+1){
        rep1(j,pow2(10)) ndp[j]=0;
        rep1(j,10) for(int mask=good[j]; mask; mask=(mask-1)&good[j]) ndp[(mask&~(pow2(j)-1))|pow2(j)]+=dp[mask];
        rep1(j,pow2(10)) dp[j]=ndp[j];
    }
    modint res=0;
    rep(pow2(10)) res+=dp[i];
    print(res);
}

signed main(){
    ios_base::sync_with_stdio(0),cin.tie(0);
    // #ifdef i_am_noob
    // freopen("input1.txt","r",stdin);
    // freopen("output1.txt","w",stdout);
    // freopen("output2.txt","w",stderr);
    // #endif
    cout << fixed << setprecision(15);
    int t;
    #ifdef wiwihorz
    cin >> t;
    #else
    t=1;
    #endif
    ld start=clock();
    while(t--) orzck();
    bug((clock()-start)/CLOCKS_PER_SEC);
    return 0;
}

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef long double ld;

#define F first
#define S second

const int MOD = 998244353;
const int C = 26;//XXX

void add(int &x, int y){
	x += y;
	while (x >= MOD) x -= MOD;
	while (x < 0) x += MOD;
}

const int MAXN = 5e4 + 10;

int n, m, adj[10];

int dp[2][1<<10][2];
void solve() {
    cin >> n >> m;
    for (int i = 0; i < 10; i++)
        adj[i] = 1<<i;
    while (m--) {
        int a, b; cin >> a >> b;
        adj[a] |= 1<<b;
        adj[b] |= 1<<a;
    }

    int cur = 0;
    for (int i = 0; i < 10; i++)
        dp[cur][1<<i][1] = 1;

    for (int i = 1; i < n; i++, cur ^= 1) {
        memset(dp[!cur], 0, sizeof(dp) / 2);
        for (int mask = 1; mask < 1<<10; mask++) {
            int fs = 0;
            while (!(mask>>fs&1)) fs++;
            if (dp[cur][mask][1]) {
                for (int j = 0; j <= fs; j++)
                    add(dp[!cur][mask|1<<j][1], dp[cur][mask][1]);
                for (int j = fs+1; j < 10; j++)
                    if (!(adj[j]>>fs&1))
                        add(dp[!cur][1<<j|1<<fs][0], dp[cur][mask][1]);
            }

            int sc = fs+1;
            while (sc < 10 && !(mask>>sc&1)) sc++;
            if (sc < 10 && dp[cur][mask][0]) {
                for (int j = sc+1; j < 10; j++)
                    if (!(adj[j]>>sc&1))
                        add(dp[!cur][1<<j|1<<sc][0], dp[cur][mask][0]);
                for (int j = 0; j < fs; j++)
                    add(dp[!cur][(mask^1<<fs)|1<<j][1], dp[cur][mask][0]);
                add(dp[!cur][mask][1], dp[cur][mask][0]);
                for (int j = fs+1; j <= sc; j++)
                    if ((adj[j]&mask) != mask)
                        add(dp[!cur][mask|1>>j][0], dp[cur][mask][0]);
            }
        }
    }

    int ans = 0;
    for (int i = 0; i < 1<<10; i++) {
        add(ans, dp[cur][i][0]);
        add(ans, dp[cur][i][1]);
    }
    cout << ans << "\n";
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	//cout << fixed << setprecision(6);

	int te = 1;
	//cin >> te;
	for (int w = 1; w <= te; w++){
		//cout << "Case #" << w << ": ";
		solve();
	}
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 150005;
int S;

int ast(int x, int n)
{
    int ans = 1;
    while (n)
    {
        if (n % 2 == 1)
            ans = (ans * 1LL * x) % 998244353;
        x = (x * 1LL * x) % 998244353;
        n /= 2;
    }
    return ans;
}

int n, qq;
vector<int> g[N];

int r[N];

int v[N], d[N];

bool c[N];

vector<int> uu[N];
vector<int> t[N];

int de[N];
int tin[N], tout[N], ti;
int q[N];
void dfs0(int x, int p)
{
    tin[x] = ++ti;
    if (x == p)
        de[x] = 0;
    else
        de[x] = de[p] + 1;
    q[x] = 1;
    for (int i = 0; i < g[x].size(); ++i)
    {
        int h = g[x][i];
        if (h == p)
            continue;
        dfs0(h, x);
        q[x] += q[h];
    }
    tout[x] = ti;
}
bool isp(int x, int y)
{
    return (tin[x] <= tin[y] && tin[y] <= tout[x]);
}

vector<int> pv;
void dfs(int x, int p)
{
    pv.push_back(x);

    for (int i = 0; i < t[x].size(); ++i)
    {
        int j = t[x][i];
        for (int k = 0; k < uu[j].size(); ++k)
        {
            int y = uu[j][k];
            if (!isp(y, x) || x == y)
                uu[j][k] = 0;
            else
                uu[j][k] = pv[de[y] + 1];
        }
    }

    for (int i = 0; i < g[x].size(); ++i)
    {
        int h = g[x][i];
        if (h == p)
            continue;
        dfs(h, x);
    }

    pv.pop_back();
}

ll s[N];
ll y[N];

ll vv[N];
void dfs1(int x, int p, ll v, ll vv)
{
    s[x] = (s[x] + v);
    s[x] = (s[x] + y[x] * n);

    vv = (vv + y[x] * q[x]);
    ::vv[x] = vv;
    for (int i = 0; i < g[x].size(); ++i)
    {
        int h = g[x][i];
        if (h == p)
            continue;
        if (y[x])
            dfs1(h, x, (v + y[x] * (n - q[h])), vv);
        else
            dfs1(h, x, v, vv);
    }
}

void solv()
{
    cin >> n >> qq;
    for (int i = 0; i < n - 1; ++i)
    {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    int rn = ast(n, 998244353 - 2);
    int uq = 0;
    for (int i = 1; i <= qq; ++i)
    {
        int ty;
        cin >> ty;
        if (ty == 1)
        {
            cin >> v[i] >> d[i];
        }
        else
        {
            cin >> v[i];
            d[i] = -1;
            ++uq;
        }
    }

    S = sqrt(uq * 2 + 1000);

    vector<int> u;
    for (int i = 1; i <= qq; ++i)
    {
        if (sz(u) == S)
        {
            for (int i = 0; i < sz(u); ++i)
                c[u[i]] = false;
            u.clear();
        }
        if (d[i] == -1)
        {
            uu[i] = u;
            t[v[i]].push_back(i);
        }
        else
        {
            if (!c[v[i]])
            {
                c[v[i]] = true;
                u.push_back(v[i]);
            }
        }
    }
    for (int i = 0; i < sz(u); ++i)
        c[u[i]] = false;
    u.clear();

    dfs0(1, 1);
    dfs(1, 1);

    for (int i = 1; i <= qq; ++i)
    {
        if (sz(u) == S)
        {
            dfs1(1, 1, 0, 0);

            ll ys = 0;
            for (int x = 1; x <= n; ++x)
            {
                ys = (ys + y[x] * q[x]);
            }
            for (int x = 1; x <= n; ++x)
            {
                s[x] = (s[x] + ys);
                s[x] = (s[x] - vv[x]);
            }

            for (int i = 0; i < sz(u); ++i)
            {
                c[u[i]] = false;
                y[u[i]] = 0;
            }
            u.clear();
        }
        if (d[i] == -1)
        {
            ll ans = s[v[i]];
            for (int j = 0; j < sz(u); ++j)
            {
                if (u[j] == v[i])
                    ans = (ans + y[u[j]] * n);
                else if (uu[i][j] == 0)
                    ans = (ans + y[u[j]] * q[u[j]]);
                else
                    ans = (ans + y[u[j]] * (n - q[uu[i][j]]));
            }
            ans = (ans % 998244353);
            ans = (ans * rn) % 998244353;
            cout << ans << "\n";
        }
        else
        {
            if (!c[v[i]])
            {
                c[v[i]] = true;
                u.push_back(v[i]);
            }
            y[v[i]] = (y[v[i]] + d[i]);
        }
    }
    for (int i = 0; i < sz(u); ++i)
        c[u[i]] = false;
    u.clear();
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    ios_base::sync_with_stdio(false), cin.tie(0);

    int tt = 1;
    //cin >> tt;
    while (tt--)
    {
        solv();
    }
    return 0;
}

//#define DEBUG
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define db double
#define vc vector
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#ifdef DEBUG
void debug(){
    cout<<"#\n";
}
template<typename T>void debug(T x){
    cout<<"#"<<x<<'\n';
}
template<typename T>void debug(vc<T> x){
    cout<<'[';for(auto it=x.begin();it!=x.end();++it)
    cout<<*it<<(",]"[it+1==x.end()]);cout<<'\n';
}
template<typename T>void debug(initializer_list<T> x){
    cout<<'[';for(auto it=x.begin();it!=x.end();++it)
    cout<<*it<<(",]"[it+1==x.end()]);cout<<'\n';
}
#else
#define debug(...) 917
#define assert(...) 917
#endif
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());

//modint
template<const int P>struct Z{
    int x;Z(LL y=0){if(y>=P||y<=-P)y%=P;if(y<0)y+=P;x=y;}

    friend istream &operator>>(istream& in,Z& z){LL tmp;in>>tmp,z=tmp;return in;}
    friend ostream &operator<<(ostream& out,Z& z){out<<z.x;return out;}
    operator int(){return x;}

    void operator+=(const Z& rht){x+=rht.x;if(x>=P)x-=P;}
    void operator-=(const Z& rht){x-=rht.x;if(x<0)x+=P;}
    void operator*=(const Z& rht){x=1LL*x*rht.x%P;}
    void operator^=(int rht){
        Z res=1;while(rht){if(rht&1)res*=(*this);(*this)*=(*this),rht>>=1;}x=res.x;
    }
    void operator/=(const Z& rht){*this*=rht.inv();}

    Z operator=(LL rht){return *this=Z(rht);}
    Z operator+(Z rht)const{rht+=*this;return rht;}
    Z operator-(Z rht)const{rht=-rht,rht+=*this;return rht;}
    Z operator-()const{return Z(P-x);}
    Z operator*(Z rht)const{rht*=*this;return rht;}
    Z operator^(int rht)const{Z tmp=*this;tmp^=rht;return tmp;}
    Z inv() const{assert(x!=0);return (*this)^(P-2);}
    Z operator/(Z rht)const{rht=rht.inv(),rht*=*this;return rht;}
    bool operator==(Z rht)const{return x==rht.x;}
    bool operator!=(Z rht)const{return x!=rht.x;}
};
using znt =Z<998244353>;

template<typename T>struct Matrix{
    int N,M;vc<vc<T>> a;
    Matrix(int N=0,int M=0,T x=0):N(N),M(M),a(N,vc<T>(M)){
        for(int i=0;i<N;++i)for(int j=0;j<M;++j)a[i][j]=i==j?x:(T)0;
    }
    auto& operator[](int x){return a[x];}
    Matrix<T> operator*(Matrix<T>& rht)const{
        assert(M==rht.N);
        Matrix<T> res(N,rht.M);
        for(int i=0;i<N;++i)for(int j=0;j<rht.M;++j)for(int k=0;k<M;++k)
            res[i][j]+=a[i][k]*rht[k][j];
        return res;
    }
    Matrix<T> operator^(LL x)const{
        assert(N==M);
        Matrix<T> tmp=*this,res(N,N,1);
        while(x){if(x&1)res*=tmp;x>>=1,tmp*=tmp;}
        return res;
    }
    void operator*=(const Matrix<T>& rht){*this=rht*(*this);}
    void operator^=(LL x){*this=(*this)^x;}
};

template<const int mod>struct Con{
    using znt=Z<mod>;
    vc<znt> fac,_fac;
    Con(int n):fac(n+1),_fac(n+1){
        fac[0]=1;for(int i=1;i<=n;++i)fac[i]=fac[i-1]*(znt)i;_fac[n]=fac[n].inv();
        for(int i=n-1;i>=0;--i)_fac[i]=_fac[i+1]*(znt)(i+1);
    }
    znt operator()(int n,int m){
        if(n<0||m<0||n<m)return 0;
        return fac[n]*_fac[m]*_fac[n-m];
    }
    znt operator[](int x){return fac[x];}
};

void solve(){
	int n,m;
	Con<998244353> C(10);
    cin>>n>>m;
    vc<vc<int>> g(10,vc<int>(10));
    for(int i=0;i<m;++i){
        int u,v;cin>>u>>v;
        g[u][v]=g[v][u]=1;
    }
    int MSK=1<<10;
    vc<vc<int>> h(MSK);
    for(int msk=0;msk<MSK;++msk){
        for(int j=0;j<10;++j){
            int msl=msk;
            for(int k=0;k<10;++k){
                if((msl>>k&1)&&(g[k][j]==0))msl^=(1<<k);
            }
            msl|=(1<<j);
            h[msk].pb(msl);
        }
    }
    vc<vc<znt>> dp(n+1,vc<znt>(MSK));dp[0][0]=1;
    for(int i=0;i<n;++i)for(int msk=0;msk<MSK;++msk){
        dp[i][msk]*=C._fac[__builtin_popcount(msk)];
        if(dp[i][msk]!=znt(0))for(auto msl:h[msk])dp[i+1][msl]+=dp[i][msk];
    }
    znt sum=0;
    for(int i=0;i<MSK;++i)sum+=dp[n][i]*C._fac[__builtin_popcount(i)];cout<<sum;
}

int main(){
    #ifndef DEBUG
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	#endif
	int ttt=1;
	for(int i=1;i<=ttt;++i)solve();return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long  ll;
typedef pair<int,int>  ii;

#define ff   first
#define ss   second

const int mod = 998244353;
const int N = 50002;

int dp[N][12];
int sw[12][12];
int n,m;

int go (int i, int d) {
  if (i == n) return 1;
  auto &rf = dp[i][d];
  if (rf!=-1)return rf;
  rf = 0;
  for (int nxt = 0; nxt < 10; ++nxt) {
    if (d <= nxt || !sw[d][nxt])
      rf = (rf + go(i+1, nxt)) % mod;
  }
  return rf;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);cout.tie(0);
  #ifdef LOCAL
  freopen("input.txt","r",stdin);
  #endif // LOCAL
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    int u, v; cin >> u >> v;
    sw[u][v]=1;
    sw[v][u]=1;
  }
  memset(dp,-1,sizeof dp);
  cout << go(0,0) << '\n';
}

#include<bits/stdc++.h>
#define ll long long
#define Mod(x) ((x>=MOD)&&(x-=MOD))
using namespace std;
const int MOD = 998244353;
int n,m;
ll dp[50005][11];
bool e[11][11];
ll dfs(int p,int pre)
{
	if(p==0) return 1;
	if(dp[p][pre]!=-1) return dp[p][pre];
	ll res=0;
	for(int i=0;i<=9;++i) if(!e[pre][i]||(e[pre][i]&&pre<i)) res+=dfs(p-1,i),Mod(res);
	return dp[p][pre]=res;
}
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int u,v;
		scanf("%d %d",&u,&v);
		e[u][v]=e[v][u]=1;
	}
	memset(dp,-1,sizeof dp);
	printf("%lld\n",dfs(n,10));
	return 0;
}

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

const int D = 10;
const int MOD = 998244353;

int N, M;
int adj[D], smaller[D];
int dp[2][1 << D];

void load() {
  scanf("%d%d", &N, &M);
  while (M--) {
    int u, v;
    scanf("%d%d", &u, &v);
    adj[u] |= 1 << v;
    adj[v] |= 1 << u;
    smaller[v] |= 1 << u;
  }
}

inline int add(int x, int y) {
  x += y;
  if (x >= MOD)
    return x - MOD;
  return x;
}

inline void inc(int &x, int y) {
  x = add(x, y);
}

int solve() {
  int* curr = dp[0];
  int* nxt = dp[1];
  curr[0] = 1;
  while (N--) {
    memset(nxt, 0, sizeof nxt);
    for (int i = 0; i < 1 << D; i++)
      for (int j = 0; j < D; j++)
        if (!(i & smaller[j]))
          inc(nxt[(i & adj[j]) | (1 << j)], curr[i]);
    swap(curr, nxt);
  }
  return accumulate(curr, curr + (1 << D), 0, add);
}

int main() {
  load();
  printf("%d\n", solve());
  return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define FORI(i, a, b) for (int (i) = (a); (i) < (b); (i)++)

#define ll long long
#define mp(m, n) make_pair((m), (n))

template<typename T>
void read(vector<T> &t) {FOR(i, t.size()) {cin >> t[i];}}
template<typename T> string tostring(T a) { istringstream sin; sin >> a; return sin.str(); }

// #define DEBUG

#ifdef DEBUG
template<typename T>
void _debug(string s, T x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << *it;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, map<T, K> x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << it->first << ":" << it->second;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, set<T, K> x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << *it;
    }
    cerr << endl;
}

template<typename T, typename K>
void _debug(string s, vector<pair<T, K> > x) {
    cerr << s << ":";
    for (auto it = x.begin(); it != x.end(); ++it) {
        cerr << " " << it->first << "," << it->second;
    }
    cerr << endl;
}

void _debug(string s, int x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, long long x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, double x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, string x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, char x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, size_t x) {
    cerr << s << ": " << x << endl;
}
void _debug(string s, bool x) {
    cerr << s << ": " << x << endl;
}

#define debug(x) _debug(#x, (x))
#else
#define debug(x)
#endif

#define db debug

void solve();

void pre_init();

int main() {
    ios_base::sync_with_stdio(false); std::cin.tie(0);
    pre_init();
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
    }
}

void pre_init() {}

int dp[50005][1024];

void solve() {
    int n;
    int m;
    long long mod = 998244353;
    cin >> n >> m;
    vector<vector<long long> > v(10, vector<long long>(10));
    vector<vector<long long> > to(1024);
    FOR(i, m) {
        int a, b;
        cin >> a >> b;
        if (a > b) swap(a, b);
        v[b][a] = v[a][b] = 1;
    }
    cerr << clock() << endl;
    for (int i = 0; i < 1024; i++) {
        for (int j = 0; j < 10; j++) {
            int n_mask = (1 << j);
            bool bad = false;
            for (int k = 0; k < 10; k++) {
                if (((1<<k) & i) && k > j && v[k][j]) bad = true;
                if (((1<<k) & i) && v[k][j]) {
                    n_mask |= (1 << k);
                }
            }
            if (!bad) {
                to[i].push_back(n_mask);
            }
        }
    }
    for (int i = 0; i < 10; i++) dp[0][1<<i] = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 1024; j++) {
            for (int k = 0; k < to[j].size(); k++) {
                dp[i][to[j][k]] += dp[i-1][j];
            }
        }
        for (int j = 0; j < 1024; j++) {
            dp[i][j] %= mod;
        }
    }
    long long ans = 0;
    FOR (i, 1024) {
        ans += dp[n - 1][i];
        ans %= mod;
    }
    cout << ans << endl;
    cerr << clock() << endl;
}

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

#define f first
#define s second

typedef long long ll;

const int maxn = 5e4+5;
const int mlen = (1<<10);
const int mod = 998244353;
int t, n, m;

vector<vector<int>> board;

//friendship ended with codeforces

int precalc[mlen][10];
int dp[maxn][mlen];
int ptr[mlen];
int imask[10], rmask[10];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    t=1;
    for(int i = 0; i < 9; i++)rmask[i]=((1<<(10-i))-1)<<i;
    while(t--){
        cin >> n >> m;
        while(m--){
            int a, b;
            cin >> a >> b;
            imask[a]|=(1<<b);
            imask[b]|=(1<<a);
        }
        for(int i = 0; i < mlen; i++){
            int r= 0, cmask = 0;
            for(int j = 0; j < 10; j++){
                while(r<10 && cmask < (1<<j))cmask|=i&(1<<(r++));
                if((cmask&imask[j]) != cmask || cmask < (1<<j)){
                    precalc[i][ptr[i]++]=j;
                }
            }
        }
    }
    int ans = 0;
    for(int i = 0; i < 10; i ++)dp[0][(1<<i)]=1;
    for(int i = 0; i < n-1; i++){
        for(int mask = 0; mask < mlen; mask++){
            if(!dp[i][mask])continue;
            for(int j = 0; j < ptr[mask]; j++){
                int tmp = mask&rmask[precalc[mask][j]];
                dp[i+1][tmp]+=dp[i][mask];
                if(dp[i+1][tmp] >= mod)dp[i+1][tmp]-=mod;
            }
        }
    }
    for(int mask = 0; mask < mlen; mask++){
        ans+=dp[n-1][mask];
        ans%=mod;
    }
    cout << ans;
}

#include<cstdio>
#include<algorithm>
using namespace std;

#define ll long long int
#define mod 998244353
int inc(int a,int b)
{
	return (a+b<mod)?a+b:a+b-mod;
}
int dec(int a,int b)
{
	return (a<b)?a-b+mod:a-b;
}
int mul(int a,int b)
{
	return (int)((ll)a*b%mod);
}
int pow(int a,int b)
{
	int res=1;
	while(b>0){
		if(b&1) res=mul(res,a);
		a=mul(a,a); b>>=1;
	}
	return res;
}
int inv(int x)
{
	return pow(x,mod-2);
}

int n,m,can[10][10];
int dp[50000][10];

int main(void)
{
	scanf("%d%d",&n,&m);
	while(m--){
		int v1,v2;
		scanf("%d%d",&v1,&v2);
		can[v1][v2]=can[v2][v1]=1;
	}
	for(int i=0;i<10;i++)
		dp[0][i]=1;
	for(int i=1;i<n;i++)
		for(int j=0;j<10;j++){
			dp[i][j]=0;
			for(int k=0;k<10;k++)
				if(!can[j][k]||k<j)
					dp[i][j]=inc(dp[i][j],dp[i-1][k]);
		}
	int ans=0;
	for(int i=0;i<10;i++)
		ans=inc(ans,dp[n-1][i]);
	printf("%d\n",ans);
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define M 51
#define N 50010
#define W 11
#define Z 1100
#define yu 998244353
ll n,m,u[M],v[M];
ll cha[W][Z],o[W][W];
ll f[N][Z];
ll gm[Z];
inline void push(ll &x,ll y)
{
	if(y>=yu)y=y%yu;
	if(y<0)y=(y%yu+yu)%yu;
	x+=y;
	if(x>yu)x-=yu;
	return ;
}
int main()
{
	//freopen("1.txt","r",stdin);
	cin>>n;
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>u[i]>>v[i];
		o[u[i]][v[i]]=1;
		o[v[i]][u[i]]=1;
	}
	for(int i=0;i<W-1;i++)
	{
		for(int j=0;j<(1<<(W-1));j++)
		{
			ll kz=0;
			for(int k=0;k<W-1;k++)
			{
				if(((1<<k)&j)>0)
				{
					if(o[i][k])
					{
						kz=1;
						cha[i][j]=0;
					}
					gm[j]=k;
				}
			}
			if(!kz)cha[i][j]=1;
		}
	}
	f[0][0]=1;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<(1<<(W-1));j++)
		{
			if(!f[i][j])continue;
			for(int k=0;k<W-1;k++)
			{
				if(cha[k][j])
				{
					push(f[i+1][(1<<(k))],f[i][j]);
				}else
				{
					if(k<gm[j])continue;
					push(f[i+1][j|(1<<(k))],f[i][j]);
				}
			}
		}
	}
	ll ans=0;
	for(int j=0;j<(1<<(W-1));j++)
	{
		push(ans,f[n][j]);
	}
	cout<<ans;
	return 0;
}

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

using namespace std;
const int MOD = 998244353;
void solve(int test_ind){
	int n, m;
	cin >> n >> m;
	vector<vector<bool> > g(10, vector<bool>(10, false));
	for (int i=0;i<10;++i) g[i][i] = true;
	for (int i=0;i<m;++i){
		int x, y;
		cin >> x >> y;
		g[x][y] = true;
		g[y][x] = true;
	}
	vector<vector<int> > dp(n+1, vector<int>(10));
	for (int i=0;i<10;++i) dp[n][i] = 0;

	// dp[i][j] = sum_k dp[i+1+k][nxt j] + dp[i+1+k][other j]
	for (int i=n-1;i>=0;--i){
		for (int j=0;j<10;++j){
			dp[i][j] = dp[i+1][j] + 1;
			for (int k=0;k<10;++k){
				if (g[k][j] && k <= j) continue;
				(dp[i][j] += dp[i+1][k]) %= MOD;
			}
		}
	}
	// for (int i=0;i<n;++i){
	// 	for (int j=0;j<10;++j) cout << dp[i][j] <<"  ";
	// 	cout << endl;
	// }
	// cout << endl;
	int ans = 0;
	for (int i=0;i<10;++i){
		(ans += (dp[0][i] + MOD - dp[1][i]) % MOD) %= MOD;
	}
	cout << ans << endl;
}

int main(){
	int t=1;
	//cin >> t;
	for(int i=0;i<t;i++){
		solve(i);
	}
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vl;
#define eb emplace_back
#define all0(x) begin(x), end(x)
#define all1(x) begin(x) + 1, end(x)
#define FOR(i, a, b) for(ll i=(a); i<=(b); i++)
#define ROF(i, a, b) for(ll i=(a); i>=(b); i--)
#define chkmax(x, a) x = max(x, a)
#define chkmin(x, a) x = min(x, a)

/*
    - we need to find the maximal set of integers s.t. they are not equivalent from all numbers of at most n digits.
        - i.e. we need to find the number of equivalent classes.
    - some observations?
        - claim. transitivity doesn't help much here.
            1 - 2 - 3 but 1 2 3 can never become 3 2 1.
        - claim. if u and v doesn't adjacent, then their relative order in any number will be fixed.
            because no matter how you switch, the rightmost element himself inevitably need to touch the left one.
        - %% maybe we can find some representative of each class? %%
            - use lexicographically smallest one.
            - claim. s is not representative iff exist j, exist i < j,
                s[i] < s[j] and
                forall t in [i, j - 1], swappable(s[t], s[j]);

    - we construct digit by digit, let dp[i] be subproblem's answer
        notice to construct a lexographically smallest instance, we start from LSB to MSB (i.e. add to high bit)
        we only care if the possible first character of original string can swap with the first character.
        Let dp[i][mask] be the number of equivalent classes of length i, and for every on bit in mask, exist element in that equiv class, whose first element is that bit.

        Given dp[i][mask],
            for every c in [0, 9]

            if exist t < c in mask, give up
            else,
                mask' = (c th bit and (all previous bits that happen to connected with current bit)
                dp[i + 1][mask'] += dp[i][mask];

        - @todo: remain to prove (1) why MSB is good (2) why it counts everything without duplicate (incl. duplicate char)
*/
const ll p = 998244353;
set<ll> g[50002];
ll dp[2][1025];
ll newMsk[1025][10]; bool fail[1025][10];
#define ex(a, b) (a.find(b) != a.end())
void solve(){
    ll n; cin >> n;
    ll m; cin >> m;
    FOR(i, 1, m) {
        ll u, v; cin >> u >> v;
        g[u].insert(v), g[v].insert(u);
    }
    FOR(msk, 0, (1ll << 10) - 1) FOR(tdigit, 0, 9) {
        FOR(t, 0, tdigit - 1) if (((1ll << t) & msk) && ex(g[tdigit], t)) fail[msk][tdigit] = true;
        if (!fail[msk][tdigit]) {
            newMsk[msk][tdigit] = (1ll << tdigit);
            FOR(t, 0, 9) if (((1ll << t) & msk) && ex(g[tdigit], t)) newMsk[msk][tdigit] |= (1ll << t);
        }
    }

    FOR(i, 0, 9) dp[1][1ll << i] = 1;
    FOR(i, 1, n) FOR(msk, 0, (1ll << 10) - 1) FOR(tdigit, 0, 9) if (!fail[msk][tdigit])
        dp[(i + 1) % 2][newMsk[msk][tdigit]] = (dp[(i + 1) % 2][newMsk[msk][tdigit]] + dp[i % 2][msk]) % p;
    ll ans = 0;
    FOR(msk, 0, (1ll << 10) - 1) ans = (ans + dp[n % 2][msk]) % p;
    cout << ans << endl;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);

    ll T = 1;
    // cin >> T;
    while (T--) solve();
    return 0;
}

#pragma GCC optimize("O3,no-stack-protector,unroll-loops,fast-math")
#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;

#define lim 10000005
#define kk 1000000007
#define ll long long
#define mp make_pair
#define pb push_back
#define x first
#define y second
#define sz(x) x.size()
#define vl vector<ll>
#define bug printf("Yes %d\n", tmp)
#define enter printf("\n")
#define space printf(" ")

struct yo
{
    ll sp, x, y;
    bool operator <(const yo &t) const
    {
        return sp < t.sp;
    }
};

void put(vector<ll> aa)
{
    for (int i = 0; i < aa.size(); i++)
    {
        printf(i == aa.size() - 1 ? "%lld\n" : "%lld ", aa[i]);
    }
}

#define mod (int)(1e9 + 7)
ll bg(ll x, ll y)
{ // big mod
    if (y == 1)
        return x % mod;
    else if (y % 2 == 0)
    {
        ll tmp = bg(x, y / 2);
        return ((tmp % mod) * tmp) % mod;
    }
    else
        return (bg(x, y - 1) * x) % mod;
}

typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> Multi_Set;
// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> Multi_Set; -> normal set // can change to multi_set by pair<int , occ[int]>
//*find_by_order(), order_of_key()

template <typename T = int>
class bit
{
private:
    vector<T> a;

public:
    bit(int n) { a.resize(n + 1); }

    void add(int i, T x)
    {
        for (; i < a.size(); i += i & -i)
            a[i] += x;
    }

    T sum(int i)
    {
        T ans = 0;
        for (; i > 0; i -= i & -i)
            ans += a[i];
        return ans;
    }

    void clear() { a.assign(a.size(), 0); }
};
// bit<ll > b2(300);

vl fac, inv, numinv; // ncr and fac

inline ll ncr(int n, int r)
{
    if (n < 0 || r < 0 || r > n)
        return 0;
    return fac[n] * inv[r] % mod * inv[n - r] % mod;
}
inline void calfacinv(int n)
{
    fac.reserve(n + 1);
    fac[0] = fac[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        fac[i] = fac[i - 1] * i % mod;
    }
    numinv.reserve(n + 1);
    numinv[0] = numinv[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        numinv[i] = numinv[mod % i] * (mod - mod / i) % mod;
    }
    inv.reserve(n + 1);
    inv[0] = inv[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        inv[i] = numinv[i] * inv[i - 1] % mod;
    }
    return;
}

/* SOS DP
for(int i = 0;i < N; ++i) for(int mask = 0; mask < (1<<N); ++mask){ //order is not important
    if(mask & (1<<i))
        F[mask] += F[mask^(1<<i)];
}
*/

ll t, n, m, k, ans, l, r, mi, tot, cnt, ww, qq, arr[500005];
string ss, s[500005];
vector<int> bb, aa;
map<int, int> mm;
ll power[5005][20];
ll pref[500005];
ll modd = 998244353;
ll dp[2][1100];
ll edge[105][105];
ll premask[1024][15];

int bt(int x){
    return (1<<x);
}

void solve(){

    cin >> n;
    cin >> m;
    for (int i=0;i<m;i++){
        int a, b;
        cin >> a >> b;
        edge[a][b] = edge[b][a] = 1;
    }

    //precompute all newmask(+1) for all mask(curr)
    for (int i=0;i<bt(10);i++){
        for (int j=0;j<10;j++){ // newest one use what
            int newstate = 0;
            int flag = 1;
            for (int k=0;k<10;k++){
                if ((bt(k)&i)){
                    if (j > k && edge[k][j]){
                        flag = 0;
                    }else if (edge[k][j]){
                        newstate |= bt(k);
                    }
                }
            }
            newstate |= bt(j);
            if (flag) premask[i][j] = newstate;
            else premask[i][j] = -1;
        }
    }
    // dp[ith digit][mask] -> meaning how many different class if ith digit is filled and the numbers in mask can be moved to the front
    for (int i=0;i<=9;i++){
        dp[1][bt(i)] = 1;
    }

    for (int i=1;i<n;i++){
        for (int j=0;j<bt(10);j++){
            dp[1-(i%2)][j] = 0;
        }
        for (int j=0;j<bt(10);j++){
            for (int k=0;k<10;k++){
                if (premask[j][k] == -1) continue;
                dp[1-(i%2)][premask[j][k]] += dp[(i%2)][j];
            }
        }
    }

    ll ans = 0;
    for (int j=0;j<bt(10);j++){
        ans = (ans + dp[(n%2)][j]) % 998244353;
    }

    cout << ans << endl;
    // vector<ll> cc;
    // cc.resize(n+5);

    // for (int i = 1; i <= n; i++){
    //     // cin >> cc[i];
    // }
    // ll cnt = 0;
    // for (int i=1;i<=n;i++){
    //     cin >> arr[i];
    // }
    // ll ans = -1;
    // for (int i=1;i<=n;i++){
    //     if (arr[i] != i-1){
    //         if (ans == -1) ans = arr[i];
    //         else ans &= arr[i];
    //     }
    // }
    // cout << ans << endl;

    // sort(arr+1, arr+n+1);

    // aa.clear();
    // for (int i=1;i<=n;i+=2){
    //     aa.pb(arr[i]);
    // }
    // int tmp = n;
    // if (tmp%2) tmp--;
    // for (int i=tmp;i>=1;i-=2){
    //     bb.pb(arr[i]);
    // }

    //cout << min(aa.size(), bb.size()) << endl;
    return;
    // for (int i=0;i<n;i++){
    //     if (i == n-1) cout << cc[i] << endl;
    //     else cout << cc[i] << " ";
    // }

    // if (ans) cout << "YES" << endl;
    // else cout << "NO" << endl;
    //		for (int i=1;i<=n;i++) cc[i] = 0;
    //		for (int i=1;i<=n;i++) printf("%d ",dd[i]);
}
int main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    t = 1;
    //cin >> t;
    while (t--){
        solve();
    }
}
/*
*/

#include<iostream>
#include<bitset>
#include<vector>
using namespace std;
constexpr int p=998244353,N=50001,MAXS=1<<10;
inline void add(int &a,int b){
	if((a+=b)>=p)a-=p;
}
bitset<10> g[10];
int f[N][MAXS];
vector<int> trans[MAXS];
int main(){
	ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;++i){
		int u,v;
		cin>>u>>v;
		g[u][v]=g[v][u]=1;
	}
	for(int S=0;S<MAXS;++S){
		for(int c=0;c<=9;++c){
			bool flag=1;
			for(int i=0;i<c;++i){
				if((S>>i&1)&&(g[c][i]||g[i][c])){
					flag=0;
					break;
				}
			}
			if(!flag)continue;
			int nS=S|(1<<c);
			for(int i=c+1;i<=9;++i){
				if((S>>i&1)&&(g[c][i]||g[i][c])){
					nS|=1<<i;
				}
			}
			trans[S].push_back(nS);
		}
	}
	f[0][0]=1;
	for(int i=0;i<=n;++i){
		for(int S=0;S<MAXS;++S){
			for(int nS:trans[S]){
				add(f[i+1][nS],f[i][S]);
			}
		}
	}
	int ans=0;
	for(int S=0;S<MAXS;++S){
		add(ans,f[n][S]);
	}
	cout<<ans;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define F first
#define S second
#define pb push_back
#define endl "\n"
#define all(x) x.begin(), x.end()
const int M = 50007;
const ll inf = 1e9;
const ll mod = 998244353;
const double pi = acos(-1);
const double eps = 1e-6;
const int dx[] = {0, -1, 0, 1}, dy[] = {1, 0, -1, 0};
const int block = 320;

int n, m, adj[12], big[12], dp[M][1030];

int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= m; ++i){
        int x, y;
        cin >> x >> y;

        if(x > y) swap(x, y);
        adj[x] |= (1 << y);
        adj[y] |= (1 << x);

        big[x] |= (1 << y);
    }

    dp[0][0] = 1;
    for(int i = 1; i <= n; ++i){
        for(int j = 0; j <= 9; ++j){
            for(int mask = 0; mask < (1 << 10); ++mask){
                int cmask = (mask | (1 << j));

                if((mask & adj[j]) == 0) dp[i][(1 << j)] = (1ll * dp[i][(1 << j)] + 1ll * dp[i - 1][mask]) % mod;
                else if((mask & big[j]) == 0) dp[i][cmask] = (1ll * dp[i][cmask] + 1ll * dp[i - 1][mask]) % mod;
            }
        }
    }

    ll ans = 0;
    for(int i = 0; i < (1 << 10); ++i) ans = (ans + 1ll * dp[n][i]) % mod;
    cout << ans << endl;
    return 0;
}

#include <bits/stdc++.h>

#define rep(i,l,r) for (int i = l; i <= r; i++)
#define per(i,r,l) for (int i = r; i >= l; i--)
#define fi first
#define se second
#define prt std::cout
#define gin std::cin
#define edl std::endl

namespace wxy{

const int N = 5e4 + 50,mod = 998244353;

typedef long long ll;

bool flag[10][1<<10];

int trans[10][1<<10];

int f[N][1<<10],G[10][10],n,m;

bool check(int t,int S) {
    rep(i,0,9) if ((i < t) && (S >> i & 1) && (G[t][i])) return false;
    return true;
}

inline void main(){
    #ifndef ONLINE_JUDGE
        freopen("in.in","r",stdin);
        freopen("out.out","w",stdout);
    #endif
    gin >> n >> m; rep(i,1,m) {int u,v; gin >> u >> v; G[u][v] = G[v][u] = 1;}
    rep(i,0,9) rep(S,0,(1<<10)-1) flag[i][S] = check(i,S);
    rep(i,0,9) rep(S,0,(1<<10)-1) {
        if (!flag[i][S]) continue;
        rep(k,0,9) if ((S>>k&1)&&(G[i][k])) trans[i][S] |= (1<<k);
    }
    rep(i,0,9) f[1][1<<i] = 1;
    rep(i,1,n-1) rep(S,0,(1<<10)-1) rep(t,0,9) if (flag[t][S])
        f[i+1][trans[t][S]] = (f[i+1][trans[t][S]] + f[i][S]) % mod;
    int res = 0; rep(S,0,(1<<10)-1) res = (res + f[n][S]) % mod;
    prt << res;
}

}signed main(){wxy::main(); return 0;}

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

#define rep(i, a, n) for(int i=(a); i<(n); ++i)
#define per(i, a, n) for(int i=(a); i>(n); --i)
#define pb emplace_back
#define mp make_pair
#define clr(a, b) memset(a, b, sizeof(a))
#define all(x) (x).begin(),(x).end()
#define lowbit(x) (x & -x)
#define fi first
#define se second
#define lson o<<1
#define rson o<<1|1
#define gmid l[o]+r[o]>>1

using ll = long long;
using ull = unsigned long long;
using pii = pair<int,int>;
using pll = pair<ll, ll>;
using ui = unsigned int;

constexpr int mod = 998244353;
constexpr int inf = 0x3f3f3f3f;
constexpr double EPS = 1e-8;
const double PI = acos(-1.0);

const int N = 5e4 + 10;

int n, m, dp[N][10];
bool vis[10][10];

inline void add(int &a, int b){
  a += b;
  if(a >= mod)  a -= mod;
}

int main(){
  int x, y;
  scanf("%d %d", &n, &m);
  clr(vis, 0);
  while(m--){
    scanf("%d %d", &x, &y);
    vis[x][y] = vis[y][x] = 1;
  }
  clr(dp, 0);
  rep(i, 0, 10) dp[1][i] = 1;
  rep(i, 1, n){
    rep(j, 0, 10){
      rep(k, 0, 10){
        if(vis[j][k] && j > k)  continue;
        add(dp[i+1][k], dp[i][j]);
      }
    }
  }
  int ans = 0;
  rep(i, 0, 10) add(ans, dp[n][i]);
  printf("%d\n", ans);
  return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
///#define int long long

const int M = 998244353;

int add(int a, int b) {
  a += b;
  if (a >= M) {
    return a - M;
  }
  if (a < 0) {
    return a + M;
  }
  return a;
}

int mul(int a, int b) {
  return a * (ll) b % M;
}

int pw(int a, int b) {
  int r = 1;
  while (b) {
    if (b & 1) {
      r = mul(r, a);
    }
    a = mul(a, a);
    b /= 2;
  }
  return r;
}

int dv(int a, int b) {
  return mul(a, pw(b, M - 2));
}

void addup(int &a,int b) {
  a=add(a,b);
}

void mulup(int &a,int b) {
  a=mul(a,b);
}

const int N=50000+7;
bool edge[10][10];
int dp[N][1<<10];

signed main() {
#ifndef ONLINE_JUDGE
  freopen ("input.txt", "r", stdin);
#endif

#ifdef ONLINE_JUDGE
  ios::sync_with_stdio(0); cin.tie(0);
#endif // ONLINE_JUDGE

  int ndim,m;
  cin>>ndim>>m;

  for (int i=1;i<=m;i++) {
    int a,b;
    cin>>a>>b;
    edge[a][b]=edge[b][a]=1;
  }

  for (int first=0;first<10;first++) {
    dp[1][1<<first]=1;
  }

  for (int len=1;len<ndim;len++) {
    for (int mask=0;mask<(1<<10);mask++) {
      int coef=dp[len][mask];
      if (coef==0) continue;

      vector<int> who;
      for (int bit=0;(1<<bit)<=mask;bit++) {
        if (mask&(1<<bit)) {
          who.push_back(bit);
        }
      }

      for (int place=0;place<10;place++) {
        bool bad=0;
        int new_mask=place;
        for (auto &pot:who) {
          if (edge[pot][place]) {
            new_mask|=(1<<place);
          }
          if (pot<place&&edge[pot][place]) {
            bad=1;
            break;
          }
        }
        if (bad) continue;
        addup(dp[len+1][new_mask],coef);
      }
    }
  }

  int sol=0;
  for (int mask=0;mask<(1<<10);mask++) {
    addup(sol,dp[ndim][mask]);
  }
  cout<<sol<<"\n";

  return 0;
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 998244353;
int n, p[500005][2];
int main()
{
// 	freopen("text.in", "r", stdin);
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int m, t;
    cin >> n >> m;
    for(int i = 1;i <= m;i ++) cin >> p[i][0] >> p[i][1];
    ll ans = 1;
    for(int i = 1;i <= n;i ++) ans *= 10, ans %= 998244353;
    ans -= m;
    if(ans < 0) ans += 998244353;
    cout << ans;
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int MOD = 998244353;

void add(int &x, int y)
{
    x += y;
    if (x >= MOD)
        x -= MOD;
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int N, M;
    cin >> N >> M;
    vector<vector<bool>> ban(10, vector<bool>(10));
    for (int i = 0; i < M; ++i)
    {
        int u, v;
        cin >> u >> v;
        ban[u][v] = 1;
    }
    vector<vector<int>> dp(N, vector<int>(10));
    for (int i = 0; i < 10; ++i)
        dp[0][i] = 1;
    for (int i = 0; i + 1 < N; ++i)
        for (int j = 0; j < 10; ++j)
            for (int k = 0; k < 10; ++k)
                if (!ban[j][k])
                    add(dp[i + 1][k], dp[i][j]);
    int res = 0;
    for (int i = 0; i < 10; ++i)
        add(res, dp[N - 1][i]);
    cout << res << '\n';
    return 0;
}