#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> usingnamespacestd; inlineintread() { int f = 1, x = 0; char ch;
do{ ch = getchar(); if (ch == '-') f = -1; }while(ch < '0' || ch > '9'); do{ x = x * 10 + ch - '0'; ch = getchar(); }while(ch >= '0' && ch <= '9'); return f * x; } constint N = 1e5; constint mod = 998244353;
int n, m; structEdge { int to, next; } edge[N + 1]; int start[N + 1], tot, d[N + 1]; int sg[N + 1], app[N + 1][600]; int w[600]; namespace gause { int mat[601][601], f[601]; inlineintpow(int x, int y) { int ans = 1;
while (y) { if (y & 1) ans = 1ll * ans * x % mod; x = 1ll * x * x % mod; y >>= 1; } return ans; } inlinevoidsolve() { for (int i = 0; i <= 599; i++) { for (int j = i + 1; j <= 599; j++) { if (!mat[j][i]) continue; int div = 1ll * mat[j][i] * pow(mat[i][i], mod - 2) % mod; for (int k = i + 1; k <= 600; k++) mat[j][k] = (mat[j][k] - 1ll * mat[i][k] * div % mod + mod) % mod; } } for (int i = 599; i >= 0; i--) { f[i] = mat[i][600]; for (int j = i + 1; j <= 599; j++) f[i] = (f[i] - 1ll * mat[i][j] * f[j] % mod + mod) % mod; f[i] = 1ll * f[i] * pow(mat[i][i], mod - 2) % mod; } return; } }
inlinevoidaddedge(int u, int v) { edge[++tot] = { v, start[u] }; start[u] = tot; d[v]++; return; } inlinevoiddfs(int u) { if (sg[u] != -1) return; for (int i = start[u]; i; i = edge[i].next) { int v = edge[i].to; dfs(v); app[u][sg[v]] = 1; } for (int i = 0; i < 600; i++) { if (!app[u][i]) { sg[u] = i; break; } } w[sg[u]]++; return; } intmain() { n = read(); m = read(); for (int i = 1; i <= m; i++) { int u = read(), v = read(); addedge(u, v); } memset(sg, -1, 4 * (N + 1));
for (int i = 1; i <= n; i++) if (!d[i]) dfs(i); for (int i = 0; i <= 600; i++) gause::mat[0][i] = 1; for (int i = 1; i <= 599; i++) { gause::mat[i][i] = (-n - 1 + mod) % mod; for (int j = 0; j <= 599; j++) gause::mat[i][j] = (gause::mat[i][j] + w[i ^ j]) % mod; } gause::solve();