zoukankan      html  css  js  c++  java
  • 【Foreign】置换 [数论][置换]

    置换

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

      

    Input

      

    Output

      

    Sample Input

      4
      2 1 4 3

    Sample Output

      3 4 2 1

    HINT

      1<=n<=10^6

    Main idea

      已知一个置换置换自己得到的序列,求这个置换。

    Solution

      显然是置换题。首先我们正向考虑,考虑一下一个置换置换自己会发生怎样的结果。

      然后我们一波画图发现:如果一个轮换的长度是奇数,那么这个环所有点连边向后移一位;如果一个轮换的长度数偶数,那么就会拆解成两个长度一样的新轮换。

      然后我们倒着来想,考虑如何合并。显然现在的轮换是奇数的话,我们将所有点连边向前移动一位。如果是偶数的话,再找一个长度和这个一样的轮换,把两个轮换并在一起,并在一起就是两个轮换依次取出一个。

      如果轮换是偶数且找不到一对的话就显然不合法。

    Code

     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<vector>
     8 #include<cmath>
     9 using namespace std;  
    10 
    11 const int ONE=1000005;
    12 
    13 int n;
    14 int x,P[ONE],d[ONE],record[ONE];
    15 int vis[ONE],cnt,tot,num;
    16 int Ans[ONE];
    17 
    18 vector <int> q[ONE]; 
    19 struct power
    20 {
    21         int len;
    22         int id;
    23 }R[ONE];
    24 int cmp(const power &a,const power &b){return a.len < b.len;}
    25 
    26 int get()
    27 {    
    28         int res=1,Q=1;char c;
    29         while( (c=getchar())<48 || c>57 )
    30         if(c=='-')Q=-1;
    31         res=c-48;
    32         while( (c=getchar())>=48 && c<=57 )
    33         res=res*10+c-48;
    34         return res*Q;
    35 }
    36 
    37 int main() 
    38 {
    39         n=get();
    40         for(int i=1;i<=n;i++) P[i]=get();
    41         
    42         for(int i=1;i<=n;i++)
    43         {
    44             if(vis[i]) continue;
    45             cnt = 0;    x = i;
    46             for(;;)
    47             {
    48                 record[++cnt]=x;
    49                 x = P[x];
    50                 vis[x] = 1;
    51                 if(x==i) break;
    52             }
    53             
    54             if(cnt==1) {Ans[i]=i; continue;}
    55             
    56             if(cnt%2==1)
    57             {
    58                 int len=1;
    59                 num=0;
    60                 for(int j=1;j<=cnt;j++)
    61                 {
    62                     d[len]=record[j];
    63                     len+=2;    if(len>cnt) len-=cnt;
    64                 }
    65                 d[cnt+1]=d[1];
    66                 for(int j=1;j<=cnt;j++)  Ans[d[j]]=d[j+1];
    67             }
    68             else
    69             {
    70                 R[++tot].id=tot;    R[tot].len=cnt;
    71                 for(int j=1;j<=cnt;j++)
    72                     q[tot].push_back(record[j]);
    73             }
    74         }
    75         
    76         if(tot%2==1) {printf("-1");exit(0);}
    77         sort(R+1,R+tot+1,cmp);
    78         
    79         for(int j=1;j<=tot;j+=2)
    80         {
    81             int x=R[j].id, y=R[j+1].id;
    82             if(R[j].len != R[j+1].len) {printf("-1");exit(0);}
    83                         
    84             num=0;
    85             for(int i=0;i<R[j].len;i++)
    86                 d[++num]=q[x][i], d[++num]=q[y][i];
    87             
    88             d[num+1]=d[1];
    89             for(int i=1;i<=num;i++) Ans[d[i]]=d[i+1];
    90         }
    91         
    92         for(int i=1;i<=n;i++) printf("%d ",Ans[i]);
    93 }
    View Code
  • 相关阅读:
    python学习day7
    python学习day4
    python 学习day6(面向对象)
    python 学习day5(模块)
    python学习之正则表达式
    python作业day4计算器
    python作业day3修改配置文件
    Python作业day2购物车
    python学习day2(二)
    操作系统 银行家算法
  • 原文地址:https://www.cnblogs.com/BearChild/p/6486319.html
Copyright © 2011-2022 走看看