QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#400908#5437. Graph Completingcomeintocalm#WA 99ms199916kbC++206.4kb2024-04-27 18:05:362024-04-27 18:05:37

Judging History

你现在查看的是最新测评结果

  • [2024-04-27 18:05:37]
  • 评测
  • 测评结果:WA
  • 用时:99ms
  • 内存:199916kb
  • [2024-04-27 18:05:36]
  • 提交

answer

#include<bits/stdc++.h>

const int p = 998244353;
typedef long long LL;
using namespace std;
const int mod = p;


const int N = 5e3+7;

template<int mod>
struct ModInt {
#define T (*this)
	int x;
	ModInt() : x(0) {}
	ModInt(int y) : x(y >= 0 ? y : y + mod) {}
	ModInt(LL y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
	inline int inc(const int &v) {
		return v >= mod ? v - mod : v;
	}
	inline int dec(const int &v) {
		return v < 0 ? v + mod : v;
	}
	inline ModInt &operator+=(const ModInt &p) {
		x = inc(x + p.x);
		return T;
	}
	inline ModInt &operator-=(const ModInt &p) {
		x = dec(x - p.x);
		return T;
	}
	inline ModInt &operator*=(const ModInt &p) {
		x = (int)((LL)x * p.x % mod);
		return T;
	}
	inline ModInt inverse() const {
		int a = x, b = mod, u = 1, v = 0, t;
		while (b > 0)t = a / b, swap(a -= t * b, b), swap(u -= t * v, v);
		return u;
	}
	inline ModInt &operator/=(const ModInt &p) {
		T *= p.inverse();
		return T;
	}
	inline ModInt operator-() const {
		return -x;
	}
	inline friend ModInt operator+(const ModInt &lhs, const ModInt &rhs) {
		return ModInt(lhs) += rhs;
	}
	inline friend ModInt operator-(const ModInt &lhs, const ModInt &rhs) {
		return ModInt(lhs) -= rhs;
	}
	inline friend ModInt operator*(const ModInt &lhs, const ModInt &rhs) {
		return ModInt(lhs) *= rhs;
	}
	inline friend ModInt operator/(const ModInt &lhs, const ModInt &rhs) {
		return ModInt(lhs) /= rhs;
	}
	inline bool operator==(const ModInt &p) const {
		return x == p.x;
	}
	inline bool operator!=(const ModInt &p) const {
		return x != p.x;
	}
	ModInt qpow(LL n) const {
		ModInt ret(1), mul(x);
		while (n > 0) {
			if (n & 1)ret *= mul;
			mul *= mul, n >>= 1;
		}
		return ret;
	}
	inline friend ostream &operator<<(ostream &os, const ModInt &p) {
		return os << p.x;
	}
	inline friend istream &operator>>(istream &is, ModInt &a) {
		LL t;
		is >> t, a = ModInt<mod>(t);
		return is;
	}
	static int get_mod() {
		return mod;
	}
#undef T
};
using Z = ModInt<mod>;

#define pb push_back

int n, m;

std::vector<int> G[N];


Z f[N][N], pw2[N*N];
int Num1[N], siz[N], siz2[N]; 

namespace tarj {
struct edge {
    int next, to;
} e[N << 2];
int ecnt, ehead[N];

int dfn_tot, bel_tot;
int dfn[N], low[N], bel[N], dep[N];
bool vis[N], bridge[N];

int n, m;

inline void AddEdge(const int u, const int v) {
    e[++ecnt] = {ehead[u], v}, ehead[u] = ecnt;
    e[++ecnt] = {ehead[v], u}, ehead[v] = ecnt;
}

void init() {
    ecnt = 1;
    dfn_tot = bel_tot = 0;
    memset(ehead, 0, sizeof(int) * (n + 1));
    memset(dfn, 0, sizeof(int) * (n + 1));
    memset(bel, 0, sizeof(int) * (n + 1));
    memset(bridge, false, sizeof(bool) * (m + 1));
}

void dfs(const int u, const int pre = -1) {
    dfn[u] = low[u] = ++dfn_tot;
    for (int i = ehead[u]; i; i = e[i].next) {
        int v = e[i].to;
        if (dfn[v] == 0) {
            dep[v] = dep[u] + 1;
            dfs(v, i);
            low[u] = std::min(low[u], low[v]);
            // printf("dbg %d %d   %d %d\n", u, v, low[v], dfn[u]);
            if (low[v] > dfn[u]) {
                bridge[i / 2] = true;
            }
        } else if (i != (pre^1)) {
            low[u] = std::min(low[u], dfn[v]);
        }
    }
}

void Shrink(const int u) {
    bel[u] = bel_tot;
    // printf("bel %d\n", bel_tot);
    ++siz2[bel_tot];
    for (int i = ehead[u]; i; i = e[i].next) {
        auto v = e[i].to;
        if (!bridge[i / 2]) {
          ++Num1[bel_tot];
        }
        if (bel[v] == 0 && !bridge[i / 2]) {
            Shrink(v);
        }
    }
}

void Tarjan() {
    dep[1] = 1;
    dfs(1);
    for (int i = 1; i <= n; ++i) {
        if (bel[i] == 0 && dfn[i] != 0) {
            ++bel_tot;
            Shrink(i);
            Num1[bel_tot] /= 2;
        }
    }
    for (int u = 1; u <= n; ++u) {
      for (int i = ehead[u]; i; i = e[i].next) {
        if (bridge[i / 2]) {
          int v = e[i].to;
          G[bel[u]].emplace_back(bel[v]);
        }
      }
    }
}

}
// number of edges of Node i, tree siz u, orginal siz u 


/*
unordered_map<int, bool> vis[N];

void dfs(int u, int fa) {
  cout << "NOW::" << u << " Num1[u]: " << Num1[u] << " siz2: " << siz2[u] << "\n";
  f[u][1] = pw2[(siz2[u])*(siz2[u]-1)/2-Num1[u]];

  siz[u] = 1;
  for(auto v : G[u]) if(v != fa) {
    dfs(v, u);
    siz[u] += siz[v];
    siz2[u] += siz2[v];
    for(int i = siz[u]; i >= 1; i--) {
      for(int j = 1; j <= min(i, siz[v]); j++) {
        /// if(connected (i, j)) i + j - 1
        /// else i + j
        Z u1 = f[u][i - j + 1], u0 = f[u][i - j], v1 = f[v][j + 1], v0 = f[v][j];
        if(u == 1 && i == 2) cout << "j::"<<j<< " "  << u1 << " " << u0 << " " << v1 << " " << v0 << " " << "\n";
        f[u][i] += u0 * v0;
        f[u][i] += u1 * v0 * (Z(siz2[u] - siz2[v]) * siz2[v] - 1);
        f[u][i] += u0 * v1 * (Z(siz2[u] - siz2[v]) * siz2[v] - 1);
      }
    }
  }
}
*/

void dfs(int u, int fa) {
  f[u][1] = pw2[(siz2[u])*(siz2[u]-1)/2-Num1[u]];
  siz[u] = 1;
  for(auto v : G[u]) if(v != fa) {
    dfs(v, u);
    siz[u] += siz[v];
    siz2[u] += siz2[v];
    vector<Z> g(n + 5);
    for(int i = 1; i <= siz[u] - siz[v]; i++) {
      for(int j = 1; j <= siz[v]; j++) {
        g[i + j - 1] += f[u][i] * f[v][j] * Z(pw2[(siz2[u] - siz2[v]) * siz2[v] - 1] - 1);
        g[i + j] += f[u][i] * f[v][j];
      }
    }
    for(int i = 1; i <= siz[u]; i++) f[u][i] = g[i];
  }
}

void init() {
  pw2[0] = 1;
  for(int i = 1; i <= 25000000; i++) pw2[i] = pw2[i - 1] * 2;
}

Z iep(Z x) {
  if(x.x & 1) return Z(998244352);
  return Z(1);
}

Z fac[N], ifac[N];
const int U = 5e3;

Z binom(Z n, Z m) {
  if(!m.x) return 1;
  if(!n.x) return 0;
  return fac[n.x] * ifac[m.x] * ifac[(n - m).x];
}
int main() {
  cin >> n >> m;
  

  init();
  fac[0] = 1;
  for(int i = 1; i <= U; i++) fac[i] = fac[i - 1] * i;
  ifac[U] = fac[U].inverse();
  for(int i = U - 1; i >= 1; i--) ifac[i] = ifac[i + 1] * (i + 1);
  ifac[0] = 1;
  
  
  tarj::n = n, tarj::m = m;
  
  tarj::init();
  for(int i = 1; i <= m; i++) {
    int u, v;
    cin >> u >> v;
    tarj::AddEdge(u, v);
  }
  tarj::Tarjan();
  
  dfs(1, 1);
  //cout << Num1[1] << "FUCK\n";
  
  Z ans(0);
  for(int i = 1; i <= n; i++) {
    ans = ans + binom(i, 1) * iep(i - 1) * f[1][i];
  }
  //for(int i = 1; i <= n; i++) cout << f[1][i] << " "  << "\n";
  cout << ans << "\n";
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 97ms
memory: 199616kb

input:

3 2
1 2
2 3

output:

1

result:

ok 1 number(s): "1"

Test #2:

score: 0
Accepted
time: 96ms
memory: 199668kb

input:

4 4
1 2
2 3
3 4
4 1

output:

4

result:

ok 1 number(s): "4"

Test #3:

score: -100
Wrong Answer
time: 99ms
memory: 199916kb

input:

2 1
1 2

output:

998244351

result:

wrong answer 1st numbers differ - expected: '0', found: '998244351'