Description
对于两个长度为n排列p,q,定义f(p,q)为一个排列f,满足fpi=qi
对于一个排列的序列{an},定义a1=p,a2=q,an=f(an-2,an-1)
求ak
n<=1e5,k<=1e9
Solution
我能说我抽代基础为0吗QwQ
考虑两个置换p,q之间的符合,定义为f=pq,结果为一个置换f,满足fi=pqi
再定义g=p^-1为p的逆,满足gpi=i,逆有个性质就是
(
p
q
)
−
1
=
q
−
1
p
−
1
(pq)^{-1}=q^{-1}p^{-1}
(pq)−1=q−1p−1
那么我们可以知道f(p,q)=qp^-1
考虑把a的前几项写出来:
a
1
=
p
a_1=p
a1=p
a
2
=
q
a_2=q
a2=q
a
3
=
q
p
−
1
a_3=qp^{-1}
a3=qp−1
a
4
=
q
p
−
1
q
−
1
a_4=qp^{-1}q^{-1}
a4=qp−1q−1
a
5
=
q
p
−
1
q
−
1
p
q
−
1
a_5=qp^{-1}q^{-1}pq^{-1}
a5=qp−1q−1pq−1
a
6
=
q
p
−
1
q
−
1
p
p
q
−
1
a_6=qp^{-1}q^{-1}ppq^{-1}
a6=qp−1q−1ppq−1
a
7
=
q
p
−
1
q
−
1
p
p
p
−
1
q
p
q
−
1
a_7=qp^{-1}q^{-1}ppp^{-1}qpq^{-1}
a7=qp−1q−1ppp−1qpq−1
a
8
=
q
p
−
1
q
−
1
p
q
p
−
1
q
p
q
−
1
a_8=qp^{-1}q^{-1}pqp^{-1}qpq^{-1}
a8=qp−1q−1pqp−1qpq−1
注意这里a7写成这样是为了契合我们找到的规律
设
A
=
q
p
−
1
q
−
1
p
A=qp^{-1}q^{-1}p
A=qp−1q−1p
我们可以发现
a
7
=
A
a
1
A
−
1
,
a
8
=
A
a
2
A
−
1
a_7=Aa_1A^{-1},a_8=Aa_2A^{-1}
a7=Aa1A−1,a8=Aa2A−1
那么我们可以归纳出,
∀
i
>
6
,
a
i
=
A
a
i
−
6
A
−
1
\forall i>6,a_i=Aa_{i-6}A^{-1}
∀i>6,ai=Aai−6A−1
然后我们就只需要求出
A
m
A^m
Am,这东西可以直接把所有轮换找出来然后位移
复杂度O(n)
Code
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
typedef vector<int> vec;
int n,k,c[N];
bool vis[N];
vec a[7],A,p,q;
vec inv(vec a) {
vec b;b.resize(n);
fo(i,0,n-1) b[a[i]]=i;
return b;
}
vec mult(vec a,vec b) {
vec c;c.resize(n);
fo(i,0,n-1) c[i]=a[b[i]];
return c;
}
vec pwr(vec a,int t) {
vec b;b.resize(n);
fo(i,0,n-1) vis[i]=0;
fo(i,0,n-1)
if (!vis[i]) {
if (a[i]==i) {b[i]=i;continue;}
int x=i,m=0;
do {vis[c[m++]=x]=1;x=a[x];} while (x!=i);
fo(j,0,m-1) b[c[j]]=c[(j+t)%m];
}
return b;
}
int main() {
scanf("%d%d",&n,&k);
p.resize(n);q.resize(n);
fo(i,0,n-1) scanf("%d",&p[i]),p[i]--;
fo(i,0,n-1) scanf("%d",&q[i]),q[i]--;
a[1]=p;a[2]=q;
if (n<=6) {
fo(i,3,n) a[i]=mult(a[i-1],inv(a[i-2]));
fo(i,0,n-1) printf("%d ",a[n][i]+1);
return 0;
}
fo(i,3,6) a[i]=mult(a[i-1],inv(a[i-2]));
A.resize(n);fo(i,0,n-1) A[i]=i;
A=mult(A,q);A=mult(A,inv(p));A=mult(A,inv(q));A=mult(A,p);
A=pwr(A,(k-1)/6);
vec an=a[(k-1)%6+1];
an=mult(A,an);an=mult(an,inv(A));
fo(i,0,n-1) printf("%d ",an[i]+1);
return 0;
}