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