首页 > 其他分享 >arc143

arc143

时间:2022-09-07 10:56:52浏览次数:44  
标签:int dfs arc143 ++ vector mathcal adj

\(\textbf{B.}\)

发现一个符合条件的矩阵 \(a\) 当且仅当 \(\forall (i,j)\), "\(a_{i,j}\) 是 \(a_{i,k}\) 中的最大值"和"\(a_{i,j}\) 是 \(a_{k,j}\) 中的最小值"不同时成立.

考虑容斥. 注意到若同时存在 \((i,j),(x,y)\) 均不满足如上条件, 显然 \(i\neq x,j\neq y\).

则 \(\begin{cases}a_{i,j}>a_{i,y},a_{x,y}<a_{i,y}\;\;\to\;\;a_{i,j}>a_{x,y}\\a_{i,j}<a_{x,j},a_{x,y}>a_{x,j}\;\;\to\;\;a_{i,j}<a_{x,y}\end{cases}\), 矛盾!

于是容斥时枚举格子 \((i,j)\) 及 \(a_{i,j}=k\), 为 \(\dbinom{k-1}{n-1}(n-1)!\cdot\dbinom{n^2-k}{n-1}(n-1)!\cdot((n-1)^2)!\).

于是最终答案为: \((n^2)!-n^2\sum_{k}\cdot\dbinom{k-1}{n-1}(n-1)!\cdot\dbinom{n^2-k}{n-1}(n-1)!\cdot((n-1)^2)!\).

直接计算即可 \(\mathcal{O}(n^2)\).

void solve(){
	int n; cin >> n;
	Binom binom(n * n);
	modint ans = binom.fact(n * n);
	for(int k = 1; k <= n * n; k ++)
		ans -= modint(n * n) * binom.binom(k - 1, n - 1) * binom.binom(n * n - k, n - 1) * binom.fact(n * n - 2 * n + 1) * binom.fact(n - 1).qpow(2);
	cout << ans.val() << '\n';
}

\(\textbf{C.}\)

考虑设 \(b_i=a_i\bmod{x+y}\). 则:

  • 若存在 \(1 \leq i \leq n\), 使得 \(y\leq b_i<x\), 则后手必胜.
  • 若以上不成立且存在 \(1 \leq i \leq n\), 使得 \(x\leq b_i\), 则先手必胜.
  • 若以上均不成立, 则后手必胜.
void solve(){
	int n, x, y; cin >> n >> x >> y;
	vector<int> val(n); for(int i = 0; i < n; i ++) cin >> val[i], val[i] %= (x + y);
 
	for(int i = 0; i < n; i ++) if(y <= val[i] && val[i] < x){cout << "Second" << '\n'; return;}
	for(int i = 0; i < n; i ++) if(x <= val[i]){cout << "First" << '\n'; return;}
	cout << "Second" << '\n';
}

\(\textbf{D.}\)

建无向图 \(\mathcal{G}\), 其中 \(V_\mathcal{G}=\{1,\cdots,n\}\), \(E_\mathcal{G}=\{(a_i,b_i):i=1,\cdots,m\}\). 设原题中的无向图为 \(\mathcal{G}'\).

则对于 \(\mathcal{G}\) 中的桥 \((u,v)\), 无论其如何定 01 均会在 \(\mathcal{G}'\) 中作为桥.

下面分别考虑 \(\mathcal{G}\) 中的所有边双连通分量. 对于每个 \(\mathcal{G}\) 中的边双连通分量, 可将其定向成为一个强连通分量. 于是按照这个定向定出 0 边和 1 边. 则 \(\mathcal{G}'\) 对于这些点是一个强连通分量.

所以在 tarjan 的时候对树边定正向, 返祖边定反向即可. 时间复杂度: \(\mathcal{O}(n+m)\).

void solve(){
	int n, m; cin >> n >> m;
	vector<int> p(m); for(int i = 0; i < m; i ++) cin >> p[i], p[i] --;
	vector<int> q(m); for(int i = 0; i < m; i ++) cin >> q[i], q[i] --;
 
	vector<vector<pair<int, int>>> adj(n);
	for(int i = 0; i < m; i ++) adj[p[i]].push_back({q[i], 2 * i}), adj[q[i]].push_back({p[i], 2 * i + 1});
 
	vector<int> ans(m);
 
	vector<int> dfn(n, -1), low(n, -1); int pdfn = 0;
	stack<int> stk;
	vector<int> ebcc(n, -1); int pebcc = 0;
	auto dfs_ebcc = [&](auto dfs_ebcc, int u, int frm = -1) -> void {
		dfn[u] = low[u] = pdfn ++;
		stk.push(u);
		for(auto [v, idx] : adj[u]){
			if(dfn[v] == -1) ans[idx >> 1] = idx % 2, dfs_ebcc(dfs_ebcc, v, idx), low[u] = min(low[u], low[v]);
			else if(frm != (idx ^ 1)) ans[idx >> 1] = 1 - idx % 2, low[u] = min(low[u], dfn[v]);
		}
		if(dfn[u] == low[u]){while(ebcc[u] == -1) ebcc[stk.top()] = pebcc, stk.pop(); pebcc ++;}
	} ;
 
	for(int i = 0; i < n; i ++) if(dfn[i] == -1) dfs_ebcc(dfs_ebcc, i);
 
	for(int i = 0; i < m; i ++) cout << ans[i]; cout << '\n';
}

\(\textbf{E.}\)

记 \(c_u\) 表示 \(u\) 的颜色(\(0\) 为白色, \(1\) 为黑色). 则 \(\forall v\in\mathrm{son}(u)\),

  • 若 \(c_v=0\), 则只需要让 \(v\) 比 \(u\) 后染色, 此时 \(c_u\) 取反.
  • 若 \(c_v=1\), 则只需要让 \(u\) 比 \(v\) 后染色, 此时 \(c_u\) 不变.

所以从 \(1\) 作为根按照上面更新方式dfs, 若 \(c_1=1\) 显然无解, 否则上述的 \(n-1\) 条限制是充要条件, 之后只需要 toposort 找到最小的符合条件的排列即可.

于是就做完了. 时间复杂度: \(\mathcal{O}(n\log n)\).

struct Topo{
private:
	vector<vector<int>> adj; vector<int> deg; int n;
public:
	void clear(int _n){n = _n, deg = vector<int>(n), adj = vector<vector<int>>(n);}
	void add(int u, int v){adj[u].push_back(v), deg[v] ++;}
	vector<int> topo(){
		vector<int> ans;
		set<int> s; for(int i = 0; i < n; i ++) if(!deg[i]) s.insert(i);
		while(!s.empty()){
			int u = *s.begin(); s.erase(u); ans.push_back(u);
			for(int v : adj[u]){deg[v] --; if(!deg[v]) s.insert(v);}
		}
		assert((int)ans.size() == n);
		return ans;
	}
} ;
 
void solve(){
	int n; cin >> n;
	vector<vector<int>> adj(n);
	for(int i = 0; i < n - 1; i ++){
		int u, v; cin >> u >> v; u --, v --;
		adj[u].push_back(v), adj[v].push_back(u);
	}
	string str; cin >> str;
 
	Topo topo; topo.clear(n); vector<int> col(n);
	auto dfs = [&](auto dfs, int u, int pa) -> void {
		col[u] = (str[u] == 'B');
		for(int v : adj[u]) if(v != pa){
			dfs(dfs, v, u);
			if(!col[v]) col[u] ^= 1, topo.add(v, u);
			else topo.add(u, v);
		}
	} ;
	dfs(dfs, 0, -1);
 
	for(int i = 0; i < n; i ++) 
 
	if(col[0]){cout << -1 << '\n'; return;}
	vector<int> ans = topo.topo(); for(int i = 0; i < n; i ++) cout << ans[i] + 1 << ' '; cout << '\n';
}

\(\textbf{F.}\)

咕咕咕.

标签:int,dfs,arc143,++,vector,mathcal,adj
From: https://www.cnblogs.com/zhangmj2008/p/arc143.html

相关文章