题面
🔗
N
≤
1
0
5
,
K
≤
1
0
9
N\leq 10^5,K\leq 10^9
N≤105,K≤109
题解
我们定义两个矩阵 A , B A,B A,B 代表排列 p , q p,q p,q ,具体地, A i , p i = 1 , B i , q i = 1 A_{i,p_i}=1,B_{i,q_i}=1 Ai,pi=1,Bi,qi=1 ,那么, f ( p , q ) f(p,q) f(p,q) 的矩阵就是 A T B A^{T}B ATB 。 A T A^{T} AT 为 A A A 的转置矩阵,由排列的性质可得 A T A A^{T}A ATA 等于 “1” 矩阵。
为了简化推导,我们用 A
,B
,a
,b
分别表示
A
,
B
,
A
T
,
B
T
A,B,A^{T},B^{T}
A,B,AT,BT 。现在我们把前面几项列出来找规律。
A
B
aB
b a B
bA b aB
bA Ab aB
bAB A baB
bABa B AbaB
bABa aB AbaB
bABab a BAbaB
......
可以发现,长度变化很有规律,每三个连续加一,然后加二,从第二个开始长度依次是 1 , 2 , 3 , 5 , 6 , 7 , 9 , 10 , 11 , . . . . . . 1,2,3,5,6,7,9,10,11,...... 1,2,3,5,6,7,9,10,11,......
最中心的一到两个矩阵依次是 A , B , a B , a , b , A b A,B,aB,a,b,Ab A,B,aB,a,b,Ab 循环;
剩下的部分,左边是 bABa
重复拼接无穷次的前缀,右边是左边部分的置换。
所以我们用“排列变换”快速幂处理左边和右边,时间复杂度 O ( n log n ) O(n\log n) O(nlogn) 。
CODE
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<unordered_map>
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast")
using namespace std;
#define MAXN 100005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define PR pair<int,int>
// #define int LL
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
// #define getchar() xchar()
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
int n,m,s,o,k;
int A[MAXN],B[MAXN],a[MAXN],b[MAXN];
int t4[MAXN],mi[MAXN],pr[MAXN],tl[MAXN];
void revp(int *A,int *B) {
for(int i = 1;i <= n;i ++) B[A[i]] = i;
return ;
}
void mult(int *A,int *B,int *C) {
for(int i = 1;i <= n;i ++) {
C[i] = B[A[i]];
} return ;
}
int main() {
n = read(); m = read();
for(int i = 1;i <= n;i ++) {
A[i] = read();
a[A[i]] = i;
}
for(int i = 1;i <= n;i ++) {
B[i] = read();
b[B[i]] = i;
}
if(m == 1) {
for(int i = 1;i <= n;i ++) AIput(A[i],i==n ? '\n':' ');
return 0;
}
int ty = m % 6,le = (m-2)/3 + m-1;
if(le & 1) le = le/2;
else le = le/2-1;
if(ty == 1) for(int i = 1;i <= n;i ++) mi[i] = A[i];
else if(ty == 2) for(int i = 1;i <= n;i ++) mi[i] = B[i];
else if(ty == 3) mult(a,B,mi);
else if(ty == 4) for(int i = 1;i <= n;i ++) mi[i] = a[i];
else if(ty == 5) for(int i = 1;i <= n;i ++) mi[i] = b[i];
else mult(A,b,mi);
mult(b,A,t4); mult(B,a,tl);
mult(t4,tl,t4);
int nm = (le>>2),el = le&3;
for(int i = 1;i <= n;i ++) pr[i] = i;
while(nm > 0) {
if(nm & 1) mult(pr,t4,pr);
for(int i = 1;i <= n;i ++) tl[i] = t4[i];
mult(t4,tl,t4); nm >>= 1;
}
if(el >= 1) mult(pr,b,pr);
if(el >= 2) mult(pr,A,pr);
if(el >= 3) mult(pr,B,pr);
revp(pr,tl);
mult(pr,mi,pr); mult(pr,tl,pr);
for(int i = 1;i <= n;i ++) AIput(pr[i],i==n ? '\n':' ');
return 0;
}
/*
A,B,aB,a,b,Ab
A
B
aB
baB
bAbaB
bAAbaB
bABAbaB
bABaBAbaB
bABaaBAbaB
bABabaBAbaB
bABabAbaBAbaB
bABabAAbaBAbaB
bABabABAbaBAbaB
bABabABaBAbaBAbaB
bABabABaaBAbaBAbaB
*/