#ifndef hari64 #include // #pragma GCC target("avx2") // #pragma GCC optimize("O3") // #pragma GCC optimize("unroll-loops") #define debug(...) #else #include "util/viewer.hpp" #define debug(...) viewer::_debug(__LINE__, #__VA_ARGS__, __VA_ARGS__) #endif // clang-format off using namespace std; template using vc = vector; template using vvc = vector>; template using vvvc = vector>; using ll = long long; using ld = long double; using pii = pair; using pll = pair; using tiii = tuple; using tlll = tuple; using vi = vc; using vvi = vvc; using vvvi = vvvc; using vll = vc; using vvll = vvc; using vvvll = vvvc; using vb = vc; using vvb = vvc; using vvvb = vvvc; using vpii = vc; using vvpii = vvc; using vpll = vc; using vvpll = vvc; using vtiii = vc; using vvtiii = vvc; using vtlll = vc; using vvtlll = vvc; #define ALL(x) begin(x), end(x) #define RALL(x) (x).rbegin(), (x).rend() constexpr int INF = 1001001001; constexpr long long INFll = 1001001001001001001; template bool chmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; } template bool chmin(T& a, const T& b) { return a > b ? a = b, 1 : 0; } // clang-format on // clang-format off namespace internal{templateusing is_signed_int128=typename conditional::value||is_same::value,true_type,false_type>::type;templateusing is_unsigned_int128=typename conditional::value||is_same::value,true_type,false_type>::type;templateusing is_integral=typename conditional::value||is_signed_int128::value||is_unsigned_int128::value,true_type,false_type>::type; templateusing is_signed_int=typename conditional<(is_integral::value&&is_signed::value)||is_signed_int128::value,true_type,false_type>::type;templateusing is_unsigned_int=typename conditional<(is_integral::value&&is_unsigned::value)||is_unsigned_int128::value,true_type,false_type>::type;templateusing is_signed_int_t=enable_if_t::value>;templateusing is_unsigned_int_t=enable_if_t::value>; constexpr long long safe_mod(long long x,long long m){x%=m;if(x<0)x+=m;return x;}struct barrett{unsigned int _m;unsigned long long im;explicit barrett(unsigned int m):_m(m),im((unsigned long long)(-1)/m+1){}unsigned int umod()const{return _m;}unsigned int mul(unsigned int a,unsigned int b)const{unsigned long long z=a;z*=b;unsigned long long x=(unsigned long long)(((unsigned __int128)(z)*im)>>64);unsigned int v=(unsigned int)(z-x*_m);if(_m<=v)v+=_m;return v;}}; 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;}constexpr pairinv_gcd(long long a,long long b){a=safe_mod(a,b);if(a==0)return{b,0};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;auto tmp=s;s=t;t=tmp;tmp=m0;m0=m1;m1=tmp;}if(m0<0)m0+=b/s;return{s,m0};} 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;constexpr long long bases[3]={2,7,61};for(long long a:bases){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;}templateconstexpr bool is_prime=is_prime_constexpr(n);} // namespace internal templatestruct static_modint{using mint=static_modint;static constexpr int mod(){return m;}static mint raw(int v){mint x;x._v=v;return x;}static_modint():_v(0){}template* =nullptr>static_modint(T v){long long x=(long long)(v%(long long)(umod()));if(x<0)x+=umod();_v=(unsigned int)(x);}template* =nullptr>static_modint(T 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;} friend ostream&operator<<(ostream&os,const mint&rhs){return os<>(istream&is,mint&rhs){long long v;is>>v;v%=(long long)(umod());if(v<0)v+=umod();;rhs._v=(unsigned int)v;return is;}static constexpr bool prime=internal::is_prime;private:unsigned int _v;static constexpr unsigned int umod(){return m;}}; constexpr int MOD = 998244353;using mint=static_modint;vectormint_factorial={mint(1)};/*n>1e8 ⇒ fast_modfact(deprecated)*/mint modfact(int n){assert(n<=100000000);if(int(mint_factorial.size())<=n){for(int i=mint_factorial.size();i<=n;i++){mint next=mint_factorial.back()*i;mint_factorial.push_back(next);}}return mint_factorial[n];} /*x s.t. x^2 ≡ a (mod Prime) or -1*/mint modsqrt(mint a){long long p=mint::mod();if(a.val()==1)return a;if(a.pow((p-1)>>1).val()!=1)return -1;mint b=1,one=1;while(b.pow((p-1)>>1).val()==1)b+=one;long long m=p-1,e=0;while(m%2==0)m>>=1,e++;mint x=a.pow((m-1)>>1);mint y=a*x*x;x*=a;mint z=b.pow(m);while(y!=1){long long j=0;mint t=y;while(t!=one)j++,t*=t;z=z.pow(1ll<<(e-j-1));x*=z;z*=z;y*=z;e=j;}return x;}mint nCk(int n,int k){if(k<0||nap;mint re=a;for(long long r=1;r // clang-format off struct matrix{ vector>A; static matrix I(int n){matrix mat(n);for(int i=0;i>&vvec){A=vvec;} matrix(int n,int m):A(n,vector(m,0)){} matrix(int n,int m,T init):A(n,vector(m,init)){} matrix(int n,vector&vec):A(n,vec){} matrix(int n):A(n,vector(n,0)){} int height()const{return A.size();} int width()const{return A[0].size();} inline vector&operator[](int k){return A[k];} bool operator==(const matrix&B){int n=height(),m=width();if(n!=B.height()or m!=B.width())return false;for(int i=0;i>C(n,vector(m,0));for(int i=0;i0){if(k&1)B*=(*this);*this*=*this;k>>=1ll;}A.swap(B.A);return*this;} matrix operator+(const matrix&B)const{return(matrix(*this)+=B);} matrix operator-(const matrix&B)const{return(matrix(*this)-=B);} matrix operator*(const matrix&B)const{return(matrix(*this)*=B);} matrix operator^(const long long&k)const{return(matrix(*this)^=k);} matrix&operator+=(const T&t){int n=height(),m=width();for(int i=0;i0&&m>0);os<<" (h:"<=0;i--){sigma=y[i][h];for(int j=i+1;jLU_decomposition(){assert(height()==width());int n=height();matrix A(*(this));vectorp(n);for(int i=0;i=0?A[p[i]][k]:-A[p[i]][k]);if(absolute>=max_a)max_a=absolute,best_i=i;}int i=best_i;swap(p[i],p[k]);T w=T(1)/A[p[k]][k];for(int i=k+1;ij?A[p[i]][j]:T(0));U[i][j]=(i<=j?A[p[i]][j]:T(0));}L[i][i]=T(1);P[i][p[i]]=T(1);}return{P,L,U};} }; // clang-format on int main() { cin.tie(0); ios::sync_with_stdio(false); int N, K; cin >> N >> K; vc ABs(K); for (int i = 0; i < K; i++) { int T; cin >> T; ABs[i].resize(T); for (int j = 0; j < T; j++) { int A; int B; cin >> A >> B; A--; B--; ABs[i][j] = {A, B}; } } mint ans = 0; for (int bit = 0; bit < (1 << K); bit++) { matrix mat(N - 1, N - 1); for (int k = 0; k < K; k++) { if (bit & (1 << k)) { for (auto& [a, b] : ABs[k]) { if (a != N - 1 && b != N - 1) mat[a][b]--; if (a != N - 1 && b != N - 1) mat[b][a]--; if (a != N - 1) mat[a][a]++; if (b != N - 1) mat[b][b]++; } } } // cerr << mat << endl; debug(mat.determinant()); ans += mat.determinant() * int(pow(-1, K - __builtin_popcount(bit))); } debug(ans); cout << ans << endl; return 0; }