首页 > 其他分享 >CodeForces 1844H Multiple of Three Cycles

CodeForces 1844H Multiple of Three Cycles

时间:2024-02-28 21:37:28浏览次数:30  
标签:typedef Multiple ll 1844H nf maxn long Cycles mod

洛谷传送门

CF 传送门

首先环是不用管的,只用判环长是否为 \(3\) 的倍数即可。

考虑设 \(f(x, y, z)\) 表示 \(x\) 个 \(1\) 链,\(y\) 个 \(2\) 链,\(z\) 个 \(0\) 链,组成所有环长都为 \(3\) 的倍数的方案数。

注意到 \(f(x, y, z) = (x + y + z) f(x, y, z - 1)\)(可以接到剩下的任意一条链,或者直接成环)。所以 \(f(x, y, z) = \frac{(x + y + z)!}{(x + y)!} f(x, y, 0)\)。所以可以直接把 \(z\) 忽略,最后答案乘一个东西即可。

所以重新设 \(f(x, y)\) 表示 \(x\) 个 \(1\) 链,\(y\) 个 \(2\) 链的方案数。考虑钦定选择包含编号最小的 \(1\) 链,它可以和另外一个 \(1\) 链拼成一个 \(2\) 链,或者和 \(2\) 链拼成一个 \(0\) 链。所以有:

\[f(x, y) = (x - 1) f(x - 2, y + 1) + y (x + y - 1) f(x - 1, y - 1) \]

对称的,考虑包含编号最小的 \(2\) 链,有:

\[f(x, y) = (y - 1) f(x + 1, y - 2) + x (x + y - 1) f(x - 1, y - 1) \]

注意到 \(f(x, y), f(x - 1, y - 1), f(x - 2, y + 1), f(x + 1, y - 2)\) 知二推二,所以若维护 \(f(x, y)\) 和 \(f(x + 1, y + 1)\),我们可以从 \((x, y)\) 推到 \((x + 2, y - 1)\),或推到 \((x - 1, y + 2)\)。

考虑倒序操作。对于一次操作,可能会让 \(x, y\) 都 \(+1\),可能让其中一个 \(+2\),另一个 \(-1\)。这些都能通过已有的两个操作凑出来。

可能初始的 \((x, y)\) 不是 \((0, 0)\)。注意到初始的 \(x, y\) 一定满足 \(x \equiv y \pmod 3\),所以先推到 \(\min(x, y)\),再对其中一个不断 \(+3\) 推到它对应的那个值即可。

code
// Problem: H. Multiple of Three Cycles
// Contest: Codeforces - Codeforces Round 884 (Div. 1 + Div. 2)
// URL: https://codeforces.com/problemset/problem/1844/H
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 300100;
const ll mod = 998244353;

inline ll qpow(ll b, ll p) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = res * b % mod;
		}
		b = b * b % mod;
		p >>= 1;
	}
	return res;
}

ll n, fa[maxn], sz[maxn], a[maxn][3], fac[maxn], ifac[maxn], f = 1, g = 1, x, y, inv[maxn], ans[maxn];
bool vis[maxn];

int find(int x) {
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

// (x, y) -> (x + 2, y - 1)
inline void work1() {
	ll nf = (g - (x + 1) * (x + y + 1) % mod * f % mod + mod) % mod * inv[y] % mod;
	ll ng = ((x + 2) * g % mod + y * (x + y + 2) % mod * nf % mod + mod + mod) % mod;
	f = nf;
	g = ng;
	x += 2;
	--y;
}

// (x, y) -> (x - 1, y + 2)
inline void work2() {
	ll nf = (g - (y + 1) * (x + y + 1) % mod * f % mod + mod) % mod * inv[x] % mod;
	ll ng = ((y + 2) * g % mod + x * (x + y + 2) % mod * nf % mod + mod + mod) % mod;
	f = nf;
	g = ng;
	--x;
	y += 2;
}

void solve() {
	fac[0] = 1;
	scanf("%lld", &n);
	inv[1] = 1;
	for (int i = 2; i <= n; ++i) {
		inv[i] = (mod - mod / i) * inv[mod % i] % mod;
	}
	for (int i = 1; i <= n; ++i) {
		fa[i] = i;
		sz[i] = 1;
		fac[i] = fac[i - 1] * i % mod;
	}
	ifac[n] = qpow(fac[n], mod - 2);
	for (int i = n - 1; ~i; --i) {
		ifac[i] = ifac[i + 1] * (i + 1) % mod;
	}
	int p = -1;
	a[0][1] = n;
	for (int i = 1, x, y; i <= n; ++i) {
		for (int j = 0; j < 3; ++j) {
			a[i][j] = a[i - 1][j];
		}
		scanf("%d%d", &x, &y);
		x = find(x);
		y = find(y);
		if (x == y) {
			--a[i][sz[x] % 3];
			if (sz[x] % 3 && p == -1) {
				p = i - 1;
			}
		} else {
			--a[i][sz[x] % 3];
			--a[i][sz[y] % 3];
			fa[x] = y;
			sz[y] += sz[x];
			++a[i][sz[y] % 3];
		}
	}
	if (p == -1) {
		p = n;
	}
	for (int i = p; i; --i) {
		if (i == p) {
			ll t = min(a[i][1], a[i][2]);
			while (x < t) {
				work1();
				work2();
			}
			while (x < a[i][1]) {
				work1();
				work2();
				work1();
			}
			while (y < a[i][2]) {
				work2();
				work1();
				work2();
			}
		} else {
			if (a[i][1] == a[i + 1][1] + 1 && a[i][2] == a[i + 1][2] + 1) {
				work1();
				work2();
			} else if (a[i][1] == a[i + 1][1] + 2 && a[i][2] == a[i + 1][2] - 1) {
				work1();
			} else if (a[i][1] == a[i + 1][1] - 1 && a[i][2] == a[i + 1][2] + 2) {
				work2();
			}
		}
		ans[i] = f * fac[x + y + a[i][0]] % mod * ifac[x + y] % mod;
	}
	for (int i = 1; i <= n; ++i) {
		printf("%lld\n", ans[i]);
	}
}

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

标签:typedef,Multiple,ll,1844H,nf,maxn,long,Cycles,mod
From: https://www.cnblogs.com/zltzlt-blog/p/18041907

相关文章

  • AtCoder WTF 2019 B Multiple of Nine/南外集训 2024.2.23 T1
    给定\(q\)个区间\(\{[l_i,r_i]\}\),计算满足条件的长度为\(n\)的十进制数码串\(S\)的个数\(\bmod10^9+7\):\(\foralli\in[1,q],num(S[l_i,r_i])\equiv0\pmod9\)。其中\(num(T)\)表示数码串\(T\)代表的整数,\(T[a,b]\)表示子串\(T_aT_{a+1}\dotsT_b\)......
  • [970] Combine multiple Excel files into one Excel file with multiple sheets
    YoucancombinemultipleExcelfilesintooneExcelfilewithmultiplesheetsusingthePandaslibraryinPython.Here'sageneralapproach:ReadeachExcelfileintoaPandasDataFrame.CreateanExcelwriterobjectusingPandas.WriteeachDataFra......
  • [971] [Keep original formats] Combine multiple Excel files into one Excel file w
    IftheexistingExcelfilehasspecialformattingthatpreventsreadingitdirectlywithPandas,youcanusealibrarylikeopenpyxltohandletheappendingofnewsheets.Here'showyoucanachievethis:importosfromopenpyxlimportload_workbook......
  • CF1408E Avoid Rainbow Cycles 题解
    解题思路第一眼看过去感觉不是很可做……但是我们可以发现,如果有两个点在不同的集合中出现过,那么一定会存在彩虹环,那么两个点最多出现一次。同时我们考虑将题意转化一下,变成求最大能选取的点,使得不出现彩虹环。根据刚刚的性质,我们可以考虑每个点向它所在的集合连一条边权为\(a_......
  • Find The MultipleC++
    这题就是找N的倍数m,M要求是由1和0组成且非0。可以用图来看,从1出发临边是1和0,然后广度遍历,第一个能能整除N的数输出就行。#include<iostream>#include<queue>usingnamespacestd;intmain(){intn=-1;while(cin>>n){if(n==0)break;longlon......
  • 多模块之间的循环依赖:java: Annotation processing is not supported for module cycl
    问题描述java:Annotationprocessingisnotsupportedformodulecycles.Pleaseensurethatallmodulesfromcycle[BDCloud-business,BDCloud-admin]areexcludedfromannotationprocessing  本质:BDCloud-admin模块为主启动模块,其包含了BDCloud-business模块;但在......
  • G. Bicycles
    原题链接题记,一道思考加编写加优化耗时2h的题1.核心:抵达终点的路途中,如果换自行车,一定是换一辆速度系数更小的车2.从速度系数最小的城市出发,到达终点的cost等于其系数乘上到达终点的最小距离3.从速度系数第二小的城市出发,到达终点的最小值一定是直接往终点走和先去速度系数最......
  • [LeetCode] 1363. Largest Multiple of Three 形成三的最大倍数
    Givenanarrayofdigits digits,return thelargestmultipleof three thatcanbeformedbyconcatenatingsomeofthegivendigitsin anyorder.Ifthereisnoanswerreturnanemptystring.Sincetheanswermaynotfitinanintegerdatatype,returnt......
  • G. Bicycles 分层图单源最短路
    题目链接简单描述一下题意:给定n个点,m条带权无向边,每个点i有一辆速度系数为Si的自行车。每经过一个点即可拥有该点的自行车,在任意两点之间路过的消耗为:已经拥有的某辆自行车的速度Si*边权Wi,求从1号点到n号点的最小消耗。思路:因为需要求的是最小的总消耗,所以在某个点出发时,我......
  • G. Bicycles
    G.BicyclesAllofSlavic'sfriendsareplanningtotravelfromtheplacewheretheylivetoapartyusingtheirbikes.AndtheyallhaveabikeexceptSlavic.Thereare$n$citiesthroughwhichtheycantravel.Theyallliveinthecity$1$andwant......