ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AtCoder AGC043C Giant Graph

2022-07-11 23:08:13  阅读:147  来源: 互联网

标签:AtCoder Giant const txdy int SG AGC043C sg ll


洛谷传送门

AtCoder 传送门

学长讲的一道神仙题。

思路

由于 \(10^{18}\) 非常大,所以可以考虑这样一个贪心:每次取目前能取的 \(x+y+z\) 最大的点。因此先将所有边定向,从小的编号连向大的。

设 \(f_{x,y,z}\) 为是否选 \((x,y,z)\),那么 \(f_{x,y,z} = \prod\limits_{(x,y,z) \to (x',y',z')} [f_{x',y',z'} = 0]\),其中 \((x,y,z) \to (x',y',z')\) 表示图上有一条 \((x,y,z)\) 到 \((x',y',z')\) 的边。意思就是,若 \((x,y,z)\) 的所有出边都没选,则 \((x,y,z)\) 可以选,否则不能选。

暴力算是 \(O(n^3)\) 的,卡卡常就能过去了。

考虑图上的博弈问题:一个结点上有标记,有两个人轮流移动,每次移动可以将一个标记移动到它的任意一条出边所连向的另一个结点,无法移动的人输。

那么我们发现三个图都是独立的,并且必败态相当于 dp 中的 \(f_{x,y,z} = 1\)。因此将三个图的 \(\mathrm{SG}\) 函数算出来再异或得到整个博弈的 \(\mathrm{SG}\) 函数,答案为 \(\sum\limits_{sg_0(x)\, \oplus\, sg_1(y)\, \oplus\, sg_2(z)\, =\, 0} 10^{18(x+y+z)}\)。

注意到对于 \(m\) 条边的图的 \(\mathrm{SG}\) 函数,其最大值是 \(O(\sqrt{m})\) 级别的,因此暴力枚举 \(sg_0(x)\) 和 \(sg_1(y)\) 再根据异或的性质得到 \(sg_2(z)\)。预处理出每张图对应 \(\mathrm{SG}\) 函数的和,再相乘得到答案。总时间复杂度为 \(O(n + m)\)。

代码

code
/*

p_b_p_b txdy
AThousandMoon txdy
AThousandSuns txdy
hxy txdy

*/

#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second

using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;

const int maxn = 100100;
const int maxm = 600;
const ll mod = 998244353;
const ll base = 1000000000000000000LL % mod;

int n;

struct graph {
	int m, mxk, sg[maxn];
	bool vis[maxn];
	vector<int> G[maxn];
	ll f[maxm];
	
	void dfs(int u) {
		if (vis[u]) {
			return;
		}
		vis[u] = 1;
		set<int> st;
		for (int v : G[u]) {
			dfs(v);
			st.insert(sg[v]);
		}
		sg[u] = 0;
		while (st.find(sg[u]) != st.end()) {
			++sg[u];
		}
	}
	
	void init() {
		scanf("%d", &m);
		while (m--) {
			int u, v;
			scanf("%d%d", &u, &v);
			if (u > v) {
				swap(u, v);
			}
			G[u].pb(v);
		}
		for (int i = 1; i <= n; ++i) {
			if (!vis[i]) {
				dfs(i);
			}
		}
		ll x = 1;
		for (int i = 1; i <= n; ++i) {
			mxk = max(mxk, sg[i]);
			x = x * base % mod;
			f[sg[i]] = (f[sg[i]] + x) % mod;
		}
	}
} g[3];

void solve() {
	scanf("%d", &n);
	for (int i = 0; i < 3; ++i) {
		g[i].init();
	}
	ll ans = 0;
	for (int i = 0; i <= g[0].mxk; ++i) {
		for (int j = 0; j <= g[1].mxk; ++j) {
			ans = (ans + g[0].f[i] * g[1].f[j] % mod * g[2].f[i ^ j] % mod) % mod;
		}
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,Giant,const,txdy,int,SG,AGC043C,sg,ll
来源: https://www.cnblogs.com/zltzlt-blog/p/16468294.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有