POJ-1721 CARDS【置换群】

题意

给你一个置换 \(p\)\(p\) 只有一个环),然后每次都对自己做平方运算,就是变成 \(p^2\) ,\(p^4\) 。然后给你一个置换 \(q\),它是最初的 \(p\) 做了 \(m\) 次这样的运算得到的,就是 \(q=p^{2^m}\),求 \(p\)

题目链接:https://vjudge.net/problem/POJ-1721

分析

首先题目有个条件,置换的长度 \(n\) 为奇数,也就是 \(gcd(n,2)=1\) ,那么就相当于题目保证 \(gcd(n,2^m)=1\) 。根据置换的性质,置换 \(p\) 无论平方多少次,这个环都不会分裂。因为数据比较小,我们考虑先找到环的长度 \(len\),然后倒退即可,将 \(q\) 进行 \(len-s\%len\) 置换q求出 \(p\)

代码

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
const int N=1e3+5;
int a[N],b[N],c[N];
int solve(int n)//暴力求环的长度
{//一开始循环节多算了1
    int len=0;
    while(1)
    {
        len++;
        for(int i=1;i<=n;i++)
            b[i]=c[i];
        for(int i=1;i<=n;i++)
            c[i]=b[b[i]];
        int f=1;
        for(int i=1;i<=n;i++)
        {
            if(a[i]!=c[i])
            {
                f=0;
                break;
            }
        }
        if(f) return len;
    }
}
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        c[i]=a[i];
    }
    int len=solve(n);//cout<<"len="<<len<<endl;
    int r=len-k%len;
    for(int i=1;i<=n;i++) c[i]=a[i];
    while(r--)
    {
        for(int i=1;i<=n;i++)
            b[i]=c[i];
        for(int i=1;i<=n;i++)
            c[i]=b[b[i]];
    }
    for(int i=1;i<=n;i++)
        printf("%d\n",c[i]);
    return 0;
}

posted @ 2020-09-03 17:44  xzx9  阅读(88)  评论(0编辑  收藏  举报