Evanyou Blog 彩带

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$次,所以移动一次逆序对变化数量为奇数,那么奇数次移动逆序对数就是奇数,偶数次移动逆序对数就是偶数了。

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

代码:

 

#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;
}

 

 

 

 

posted @ 2018-07-26 21:05  five20  阅读(358)  评论(0编辑  收藏  举报
Live2D