#include #pragma GCC optimize("Ofast") #define _GLIBCXX_DEBUG using namespace std; using std::cout; using std::cin; using std::endl; using ll=long long; using ld=long double; ll ILL=1167167167167167167; const int INF=2100000000; const ll mod=998244353; #define rep(i,a) for (ll i=0;i using _pq = priority_queue, greater>; template ll LB(vector &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();} template ll UB(vector &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();} template bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;} template bool chmax(T &a,const T &b){if(a void So(vector &v) {sort(v.begin(),v.end());} template void Sore(vector &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});} void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";} namespace po167{ long long rev(long long a,long long mod){ a%=mod; long long ans=1; long long H=mod-2; while(H){ if(H&1) ans=(ans*a)%mod; a=(a*a)%mod; H>>=1; } return ans; } long long Determinant_Matrix(std::vector> G,long long MOD){ int N=G.size(); long long ans=1; for(int i=0;i> G,long long MOD){ int N=G.size(); std::vector> H(N-1,std::vector(N-1)); for(int i=0;i wei; std::vector q; int component; UFtree(int n):wei(n),component(n),par(n){ for(int i=0;i par; }; } using po167::UFtree; void solve(); // oddloop int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t=1; //cin>>t; rep(i,t) solve(); } void solve(){ int N,M; cin>>N>>M; int L=N*(N-1)/2; vector> G(N,vector(N)); UFtree T(N); rep(i,M){ int a,b; cin>>a>>b; a--,b--; G[a][b]=1; G[b][a]=1; if(T.same(a,b)) continue; L-=T.wei[T.root(a)]*T.wei[T.root(b)]; T.unite(a,b); } vector> H(N); rep(i,N){ H[T.root(i)].push_back(i); } long long A=0,B=0,ans=1; vector D; rep(i,N){ long long C=H[i].size(); if(C==0) continue; D.push_back(C); if(chmax(B,C)){ if(A> I(C,vector(C)); rep(j,C) rep(k,C){ I[j][k]=G[H[i][j]][H[i][k]]; } ans=(ans*Kirchhoffs_theorem(I,mod))%mod; } Sore(D); long long E=1; if(D.size()!=1){ if(D[0]==D[1]){ while(E<(int)D.size()&&D[E]==D[0]) E++; } else{ while(E<(int)D.size()&&D[E]==D[1]) E++; E--; } } cout<<2*(L-A*B)<<"\n"; assert(D.size()!=1); cout<<(ans*A*B*E)%mod<<"\n"; }