首页 > 其他分享 >Atcoder ARC159C Permutation Addition

Atcoder ARC159C Permutation Addition

时间:2023-07-09 18:55:07浏览次数:31  
标签:Atcoder le frac leftarrow Addition bmod mid int ARC159C

设 \(s=\sum\limits_{i = 1}^n a_i\),考虑加上排列 \(p\),那么 \(s\leftarrow s + \frac{n\times (n + 1)}{2}\)。
当有解时,因为 \(a_i\) 相等,所以有 \(s\bmod n = 0\)。

考虑 \(n \bmod 2 = 1\) 时,\(\frac{n\times (n + 1)}{2}\bmod n = 0\),所以 \(s\bmod n = 0\) 时才会有解。

然后构造方案,考虑先构造 \(2\) 个排列 \(p_i = i, p'_i = n - i + 1(1\le i\le n)\),这样的话 \(a_i\leftarrow a_i + p_i + p'_i\) 相当于 \(a_i\leftarrow a_i + (n + 1)\),\(a_i\) 之间大小没有变化。
然后进行一些变化,交换 \(p_1, p_2\) 的值,即 \(p_1 = 2, p_2 = 1, p_i = i(3\le i\le n),p'_j = n - j + 1(1\le j\le n)\),这样再 \(a_i\leftarrow a_i + p_i + p'_i\),则会是 \(a_1\leftarrow a_1 + (n + 2), a_2\leftarrow a_2 + n, a_i\leftarrow a_i + (n + 1)(3\le i\le n)\),\(a_i\) 之间大小就相当于是 \(a_1\leftarrow a_1 + 1, a_2\leftarrow a_2 - 1\)。
于是发现仅需 \(2\) 个排列就可以使 \(a_i\leftarrow a_i + 1, a_j\leftarrow a_j - 1(1\le i, j\le n)\),因为排列的值是可以是可以交换的。
于是令 \(mid = \frac{s}{n}\),一直使用上述操作使 \(a_i = mid(1\le i\le n)\) 即可,可以证明一定有方法且小于操作次数。

当 \(n\bmod 2 = 0\) 时,\(\frac{n\times (n + 1)}{2}\bmod n = \frac{n}{2}\),所以当 \(s\bmod n = 0\) 或 \(s\bmod n = \frac{n}{2}\) 有解。
当 \(s\bmod n = 0\) 时,直接用上述的做法;当 \(s\bmod n = \frac{n}{2}\) 时,先随便加一个排列 \(p\) 上去使得 \(s\bmod n = 0\),然后再用上述的做法即可。

能发现构造次数即为 \([n\bmod 2 = 0\land s\bmod n = \frac{n}{2}] + \sum\limits_{i = 1}^n |a_i - mid|\),不会超过 \(10^4\)。

// lhzawa(https://www.cnblogs.com/lhzawa/)
// Problem: C - Permutation Addition
// Contest: AtCoder - AtCoder Regular Contest 159
// URL: https://atcoder.jp/contests/arc159/tasks/arc159_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
const int N = 50 + 5;
int a[N];
int main() {
	int n;
	scanf("%d", &n);
	int sum = 0;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		sum += a[i];
	}
	if (n % 2 == 1 && sum % n != 0) {
		printf("No\n");
		return 0;
	}
	if (n % 2 == 0 && sum % n != 0 && sum % n != n / 2) {
		printf("No\n");
		return 0;
	}
	printf("Yes\n");
	int p1 = 0;
	if (n % 2 == 0 && sum % n == n / 2) {
		p1 = 1;
		sum += n * (n + 1) / 2;
		for (int i = 1; i <= n; i++) {
			a[i] += i;
		}
	}
	int mid = sum / n;
	vector<int> x, y;
	for (int i = 1; i <= n; i++) {
		for (; a[i] < mid; a[i]++) {
			x.push_back(i);
		}
		for (; a[i] > mid; a[i]--) {
			y.push_back(i);
		}
	}
	printf("%d\n", (int)(x.size()) * 2 + p1);
	if (p1) {
		for (int i = 1; i <= n; i++) {
			printf("%d ", i);
		}
		printf("\n");
	}
	for (size_t i = 0; i < x.size(); i++) {
		int u = x[i], v = y[i];
		int l = 3, r = n - 2;
		for (int j = 1; j <= n; j++) {
			printf("%d ", (j != u && j != v ? l++ : (j == u ? 2 : 1)));
		}
		printf("\n");
		for (int j = 1; j <= n; j++) {
			printf("%d ", (j != u && j != v ? r-- : (j == u ? n : n - 1)));
		}
		printf("\n");
	}
	return 0;
}

标签:Atcoder,le,frac,leftarrow,Addition,bmod,mid,int,ARC159C
From: https://www.cnblogs.com/lhzawa/p/17539175.html

相关文章

  • AtCoder Beginner Contest 309
    A:1#include<cstdio>2#include<cstring>3#include<algorithm>4#include<iostream>5#include<string>6#include<vector>7#include<stack>8#include<bitset>9#include<cstdlib>10#include......
  • AtCoder Beginner Contest 273 ABCD
    AtCoderBeginnerContest273A-ARecursiveFunctionProblemStatement题意:给你一个函数\(f(x)\)\(f(0)=1\)对于所有正整数\(k\),有\(f(k)=k*f(k-1)\)找到\(f(N)\)Solution思路:数据范围只有\(10\),直接递归。#include<bits/stdc++.h>usingnamespacestd;typede......
  • AtCoder Beginner Contest 309
    感觉F写了个乱搞做法A-Nine(abc309A)题目大意给定一个\(3\times3\)的网格,以及两个数字。问这两个数字是否水平相邻。解题思路求出两个数字的横纵坐标,看是否横坐标相同,纵坐标差一即可。读题不仔细,开题就WA了。神奇的代码#include<bits/stdc++.h>usingnamespa......
  • AtCoder Grand Contest 058 D Yet Another ABC String
    洛谷传送门AtCoder传送门OrzH6_6Q,感谢他给我们带来了这道容斥好题。这个东西看起来很不好搞。可以尝试容斥。但是我们要容斥啥?钦定ABC不出现,其他任意?感觉还是很难算。观察不合法子串,发现它们很有特点。如果我们钦定\(\texttt{A}\)为\(0\),\(\texttt{B}\)为\(1\),\(\te......
  • AtCoder Beginner Contest 308 题解
    https://atcoder.jp/contests/abc308/tasks_printA-NewScheme过水已隐藏。#include<bits/stdc++.h>#include<ext/pb_ds/assoc_container.hpp>#include<ext/pb_ds/tree_policy.hpp>#include<ext/pb_ds/hash_policy.hpp>usingnamespacestd;u......
  • AtCoder Beginner Contest 264 ABCDE
    AtCoderBeginnerContest264A-"atcoder".substr()ProblemStatement题意:截取字符串atcoder的[L,R]一段并输出。Solution题解:用string.substr直接写#include<bits/stdc++.h>usingnamespacestd;intmain(){ strings="?atcoder"; intl,r; cin&......
  • AtCoder Regular Contest 163
    A只需暴力判断能否分成两部分即可。时间复杂度\(\mathcal{O}(n^2)\)。B肯定是选值域连续的一段数操作,排序后枚举区间即可。时间复杂度\(\mathcal{O}(n\logn)\)。C场上降智了15min,我是什么shaber啊。注意到\(1=\frac1n+\sum_{i<n}\frac{1}{i(i+1)}\),但......
  • AtCoder Beginner Contest 304
    A:1#include<cstdio>2#include<cstring>3#include<algorithm>4#include<iostream>5#include<string>6#include<vector>7#include<stack>8#include<bitset>9#include<cstdlib>10#include......
  • AtCoder Beginner Contest 308 - E
    题目链接:abc308前四题简单就不放了E-MEX阿巴阿巴,比赛的时候想复杂了,一直在想怎么快速的统计27种mex的情况,啊,前面对后面的影响等等等,反正就是想复杂了现在再想想,看了官方题解,从'E'出发,统计其前后各3种数字的个数,再用mex函数判答案,\(O(n)\)即可!剩下的见代码吧,做完之后发现,没......
  • Atcoder Beginer Contest 306 D ~ E
    vp中途突然拉肚子>_<D-PoisonousFull-CourseD-PoisonousFull-Course(atcoder.jp)题意一个人初始是健康的,现在有n道菜摆在他面前,每道菜都有自已的美味值,但是有些菜是有毒的,有些菜是无毒的。如果他在健康状态吃了有毒的菜就会变成中毒状态,如果他在中毒状态吃了无毒的菜就......