首页 > 其他分享 >CodeForces 1863G Swaps

CodeForces 1863G Swaps

时间:2023-09-17 19:55:07浏览次数:43  
标签:1863G Swaps 标记 int res CodeForces maxn text mod

洛谷传送门

CF 传送门

看到 \(a_{a_i}\) 和 \(a_i \in [1, n]\),果断连边 \(i \to a_i\),得到内向基环森林。

那么每次相当于把 \(a_i\) 变成自环,连边 \(i \to a_{a_i}\)。

但是每次操作都改变图的形态很不好办,考虑打标记。

每次 \(\operatorname{swap}(a_i, a_{a_i})\),我们就把 \(i \to a_i\) 的边打上标记。那么经过若干次操作后,\(a_i\) 实际上是,不断跳出边,第一条没被打标记的边指向的点。

考虑把最终的 \(a\) 一一对应到对边打标记的方案。每个点至多有一条出边被打标记,设点 \(u\) 的入度为 \(d_u\),方案数为 \(\prod d_u + 1\)。

但是我们发现,对于一个长度为 \(k\) 的环,如果环上有 \(k - 1\) 条边被标记,那整个环就都变成自环了。

有 \(\sum\limits_{u \in \text{cycle}} d_u + 1\) 个方案对应最后环上的点全部变成自环(钦定一个点没有入边被标记或者有一条除环上边之外的入边被标记,或者整个环的边都被标记),减去 \(\sum\limits_{u \in \text{cycle}} d_u\)。因此最后答案为:

\[(\prod\limits_{u \in \text{cycle}} (d_u + 1) - \sum\limits_{u \in \text{cycle}} d_u) \prod\limits_{u \notin \text{cycle}} (d_u + 1) \]

code
// Problem: G. Swaps
// Contest: Codeforces - Pinely Round 2 (Div. 1 + Div. 2)
// URL: https://codeforces.com/problemset/problem/1863/G
// Memory Limit: 256 MB
// Time Limit: 2000 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 = 1000100;
const ll mod = 1000000007;

ll n, a[maxn], ind[maxn], fa[maxn], b[maxn];
vector<int> vc[maxn];

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

inline void merge(int x, int y) {
	x = find(x);
	y = find(y);
	if (x != y) {
		fa[x] = y;
	}
}

void solve() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		++ind[a[i]];
		fa[i] = i;
	}
	for (int i = 1; i <= n; ++i) {
		merge(i, a[i]);
	}
	for (int i = 1; i <= n; ++i) {
		vc[find(i)].pb(i);
	}
	ll ans = 1;
	for (int _ = 1; _ <= n; ++_) {
		if (vc[_].empty()) {
			continue;
		}
		int x = vc[_][0];
		while (b[x] <= 3) {
			++b[x];
			x = a[x];
		}
		ll res = 1;
		for (int x : vc[_]) {
			if (b[x] >= 3) {
				res = res * (ind[x] + 1) % mod;
			}
		}
		for (int x : vc[_]) {
			if (b[x] >= 3) {
				res = (res - ind[x] + mod) % mod;
			}
		}
		for (int x : vc[_]) {
			if (b[x] < 3) {
				res = res * (ind[x] + 1) % mod;
			}
		}
		ans = ans * res % mod;
	}
	printf("%lld\n", ans);
}

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

标签:1863G,Swaps,标记,int,res,CodeForces,maxn,text,mod
From: https://www.cnblogs.com/zltzlt-blog/p/17709635.html

相关文章

  • CF1863G
    简洁的题面,深邃的思想。首先,一个经典的套路是:对于序列中涉及到对于\(a_{a_i}\)和\(a_i\)进行操作的问题,一般可以考虑建立\((i,a_i)\)的内向基环树或者\((a_i,i)\)的外向基环树转化为图论问题。我们建立\((i,a_i)\)的内向基环树,\(swap(a_i,a_{a_i})\impliesa'_i=a_......
  • Codeforces Global Round 17 A. Anti Light's Cell Guessing
    给一个\(n\timesm\)的网格,里面藏了一个炸弹\((x_0,y_0)\)。你可以选择\(k\)个坐标\((x_1,y_1),(x_2,y_2),\cdots,(x_k,y_k)\)。第\(i\)次选择计算机会回复你一个数\(d_i=|x_0-x_i|+|y_0-y_i|\)。至少需要选出多少个坐标才能确定\((x_0,y_0)\)的位......
  • Codeforces Round 764 (Div. 3) B. Make AP
    有三个正整数\(a,b,c\)。需要执行以下操作严格一次:选择任意一个正整数\(m\)并让严格一个\(a,b,c\)之一乘以\(m\)。但不能改变他们的顺序。回答是否可以经过一次操作后使\(a,b,c\)变为等差。分类讨论题:三种情况满足一种即可。(已知\(a,b,c\geq1\))\(ma......
  • Codeforces Round 773 (Div. 2) B. Power Walking
    有\(n\)个增幅道具,第\(i\)个道具种类为\(a_i\),一个人的强度\(w\)为他所有道具的种类数。对于\(k]\in[1,n]\),询问将\(n\)个道具分配给\(k\)个人且每个人至少分配到一个道具后,能够得到的最想强度和\(\sum_{i=1}^{n}w_i\)。观察一:最低强度和\(\sum_{i=1}^{k}w......
  • Educational Codeforces Round 100
    B.FindTheArray对于条件二来说,1是万金油的存在,所以我们只需要把奇数位置或偶数位置全部变成1即可。因为要求差值小于\(\fracs2\),所以我可以求出奇偶位的和修改较小值即可。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongusingpii=pair<in......
  • codeforces图论合集
    CyclicOperations给定一个数组$a$,每次构造一个数组$\spacel\space$长度为$\spacek\space$,数组$\spacea\space$与$\spacel\space$转换关系如下:$a_{l_1}\tol_2\space,\spacea_{l_2}\tol_3\space,\spacea_{l_3}\tol_4\space,\space...\space,\spacea_{l_n}\tol_1$......
  • Codeforces Round 897 (Div. 2) 考试总结
    前言这次打得很好,相较于div3的脑残题和签到题来说,div2的思维难度更加的大。同时还有除传统题外,其他的题型出现。比如交互题等。这次能在考场上想出三道较于之前是有很大的进步的。赛时实况:ABCDE1E2F√√√××××赛后改题情况:ABCDE1E2F......
  • Codeforces 1868C/1869E Travel Plan 题解 | 巧妙思路与 dp
    题目链接:TravelPlan题目大意:\(n\)个点的完全二叉树,每个点可以分配\(1\simm\)的点权,定义路径价值为路径中最大的点权,求所有路径的价值和。对于任意长度(这里主要指包括几个节点)的路径\(t\),最大点权不超过\(k\)的方案数有\(k^t\)个,因此最大点权恰好为\(k\)的方案数有......
  • Codeforces Round 781 (Div. 2) B. Array Cloning Technique
    给一个长度为\(n\)的数组\(a\)。开始只有一份所给\(a\)的副本。你可以做以下两种操作:选择任意一个副本并且克隆它,然后将会多出一个克隆副本。交换两个元素,他们属于任意两个副本(可能是同一个)。需要判断最小操作数,使有一个副本的所有元素相同。观察一:只需要在开始的副本......
  • Codeforces Round 787 (Div. 3) B. Make It Increasing
    给一个长为\(n\)的数组\(a_1,a_2,\cdots,a_n\quad(0\leqa_i\leq10^9)\)。可以执行以下操作任意次:选择任意一个\(a_i\)并且执行\(a_i=\lfloor\frac{a_i}{2}\rfloor\)。输出最小操作次数,使得数组所有元素变为严格递增。观察:数组一些位置变小,将数组变为严......