CF986B Petr and Permutations(逆序对)
作者:互联网
题目描述
Petr likes to come up with problems about randomly generated data. This time problem is about random permutation. He decided to generate a random permutation this way: he takes identity permutation of numbers from 11 to nn and then 3n3n times takes a random pair of different elements and swaps them. Alex envies Petr and tries to imitate him in all kind of things. Alex has also come up with a problem about random permutation. He generates a random permutation just like Petr but swaps elements 7n+17n+1 times instead of 3n3n times. Because it is more random, OK?!
You somehow get a test from one of these problems and now you want to know from which one.
输入格式
In the first line of input there is one integer nn ( 103≤n≤106103≤n≤106 ).
In the second line there are nn distinct integers between 11 and nn — the permutation of size nn from the test.
It is guaranteed that all tests except for sample are generated this way: First we choose nn — the size of the permutation. Then we randomly choose a method to generate a permutation — the one of Petr or the one of Alex. Then we generate a permutation using chosen method.
输出格式
If the test is generated via Petr's method print "Petr" (without quotes). If the test is generated via Alex's method print "Um_nik" (without quotes).
题意翻译
Petr要打乱排列。他首先有一个从 11 到 nn 的顺序排列,然后进行 3n3n 次操作,每次选两个数并交换它们。
Alex也要打乱排列。他与Petr唯一的不同是他进行 7n+17n+1 次操作。
给定一个 11 到 nn 的排列。问是由谁打乱的。如果是Petr,输出"Petr",否则输出"Um_nik"(不是Alex)
感谢@AKEE 提供翻译
输入输出样例
输入 #1复制
5
2 4 5 1 3
输出 #1复制
Petr
有引理:交换一个排列的两个数,序列的逆序对的奇偶性必然发生变化。
证明可以大致yy一下:当交换的两个数x,y距离小于等于1的时候易证,当大于1的时候将两个数之间的这些数分为三部分(设较大的数为y):大于y的,小于x的以及大于x且小于y的,分别分析逆序数的变化情况即可(注意夹起来的这部分元素自己的逆序数是不变的)。因为一开始整个排列是有序的,逆序数为0,所以若最终的逆序数为奇数说明交换了奇数次,否则交换了偶数次。因此判断一下3n的奇偶性和逆序数相同还是7n+1的奇偶性和逆序数相同即可。洛谷题解区有On做法更牛逼Orz
#include <bits/stdc++.h>
#define N 1000005
using namespace std;
int n, a[1000005], b[1000005];
void add(int x, int y) {
for(; x <= N; x += (x & -x)) b[x] += y;
}
int ask(int x) {
int ans = 0;
for(; x; x -= x & -x) {
ans += b[x];
}
return ans;
}
int main() {
cin >> n;
int cnt = 0;
for(int i = 1; i <= n; i++) {
cin >> a[i];
cnt += ask(n) - ask(a[i]);//因为是排列 不会有相同的数
add(a[i], 1);
}
//逆序对数一开始是0,交换3n次后应该为偶数,交换7n+1次后应该为奇数
if((cnt & 1) == ((3 * n) & 1)) puts("Petr");
else puts("Um_nik");
return 0;
}
标签:random,Alex,nn,CF986B,Permutations,序数,Petr,逆序,permutation 来源: https://www.cnblogs.com/lipoicyclic/p/15087637.html