CF986B Petr and Permutations

题意翻译

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} 103n106 ).

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).

输入输出样例

输入样例#1: 
5
2 4 5 1 3
输出样例#1: 
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$次,所以移动一次逆序对变化数量为奇数,那么奇数次移动逆序对数就是奇数,偶数次移动逆序对数就是偶数了。

  于是我们直接树状数组求下逆序数,然后判断一下就好了。

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long 
 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
 6 using namespace std;
 7 const int N=1e6+1;
 8 int t[N+5],a[N],n;
 9 bool f;
10 
11 il int gi(){
12     int a=0;char x=getchar();
13     while(x<'0'||x>'9')x=getchar();
14     while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
15     return a;
16 }
17 
18 il void update(int k){while(k<=n)t[k]++,k+=k&-k;}
19 
20 il int query(int k){int sum=0;while(k)sum+=t[k],k-=k&-k;return sum;}
21 
22 int main(){
23     n=gi();
24     For(i,1,n) a[i]=gi();
25     Bor(i,1,n) {
26         f^=(query(a[i]-1)&1);
27         update(a[i]);
28     }
29     if(n&1) f?puts("Petr"):puts("Um_nik");
30     else f?puts("Um_nik"):puts("Petr");
31     return 0;
32 }

猜你喜欢

转载自www.cnblogs.com/five20/p/9370381.html