题意翻译
Petr要打乱排列。他首先有一个从 111 到 nnn 的顺序排列,然后进行 3n3n3n 次操作,每次选两个数并交换它们。
Alex也要打乱排列。他与Petr唯一的不同是他进行 7n+17n+17n+1 次操作。
给定一个 111 到 nnn 的排列。问是由谁打乱的。如果是Petr,输出"Petr",否则输出"Um_nik"(不是Alex)
感谢@AKEE 提供翻译
题目描述
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 1 1 1 to n n n and then 3n 3n 3n 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+1 7n+1 7n+1 times instead of 3n 3n 3n 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 n n n ( 103≤n≤106 10^{3} le n le 10^{6} 103≤n≤106 ).
In the second line there are n n n distinct integers between 1 1 1 and n n n — the permutation of size n n n from the test.
It is guaranteed that all tests except for sample are generated this way: First we choose n n n — 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).
输入输出样例
5
2 4 5 1 3
Petr
说明
Please note that the sample is not a valid test (because of limitations for n n n ) and is given only to illustrate input/output format. Your program still has to print correct answer to this test to get AC.
Due to randomness of input hacks in this problem are forbidden.
Solution:
本题思路贼有意思。
开始题意没理解,所以简述下题意:给你一个$1——n$的排列,它是由初始为从$1——n$的序列每次交换任意两位得到的,然后A进行了$3n$次操作,$B$进行了$7n+1$次操作,要你判断这个排列是谁操作出来的。
不难发现$3n$和$7n+1$奇偶性一定互异(显然),然后有一个很重要的性质,那就是排列中逆序数的奇偶性和操作的奇偶性相同,证明:1、首先每次若交换相邻的两位,则必然使得逆序数$+1$或$-1$; 2、任意交换两位,可以理解为先将后面的一个向前移动$k$位,再将前面要移的一位向后移$k-1$位,注意到共移动了$2k-1$次,所以移动一次逆序对变化数量为奇数,那么奇数次移动逆序对数就是奇数,偶数次移动逆序对数就是偶数了。
于是我们直接树状数组求下逆序数,然后判断一下就好了。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) using namespace std; const int N=1e6+1; int t[N+5],a[N],n; bool f; il int gi(){ int a=0;char x=getchar(); while(x<'0'||x>'9')x=getchar(); while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar(); return a; } il void update(int k){while(k<=n)t[k]++,k+=k&-k;} il int query(int k){int sum=0;while(k)sum+=t[k],k-=k&-k;return sum;} int main(){ n=gi(); For(i,1,n) a[i]=gi(); Bor(i,1,n) { f^=(query(a[i]-1)&1); update(a[i]); } if(n&1) f?puts("Petr"):puts("Um_nik"); else f?puts("Um_nik"):puts("Petr"); return 0; }