题意:
首先说一下什么是轮换吧,就给出一个
P
=
(
a
,
c
,
d
,
e
)
P=(a,c,d,e)
P=(a,c,d,e),那么对应的置换就是
(
a
b
c
d
e
c
b
d
e
a
)
\begin{gathered} \begin{pmatrix} a & b & c & d& e \\ c & b & d & e & a \end{pmatrix} \end{gathered}
(acbbcddeea)其中
a
a
a 的下面对应的是
P
P
P 中
a
a
a 的下一个,也就是
c
c
c,而
b
b
b 在
P
P
P 中没有出现过,因此它下面对应的是它自己。特别的,
e
e
e 的下一个是
a
a
a,也就是说最后一个的下一位是第一个。
而两个置换的复合,就像题面中说明的那样,用第一个置换的第二行和第二个置换的第一行相对应,然后形成一个新的置换,这个在题面中已经解释的很详细了。
思路:
首先我承认,我脑子有坑,一开始想把这道题搞成矩阵快速幂,然后东哥一句棒喝,让我认识到离散数学是真的没有学透……
首先,置换满足结合律(证明略),也就是说可以先算后面的 m m m 次 P 2 P_{2} P2 的置换,最后再和 P 1 P_{1} P1 算一次就够了。
然后我们可以发现,一个 P 2 P_{2} P2的话,第一行每一个元素对应的是 P P P 中相应位置的下一个;而 P 2 ∗ P 2 P_{2}*P_{2} P2∗P2,相当于每一个元素对应的是 P P P 中相应位置的下一个的下一个,即 P P P 整体向右对应两位。如果是 m m m 个 P 2 P_{2} P2的话呢?自然是每一个数都对应它相应位置的之后 m % k 2 m\%k_{2} m%k2个,毕竟这是一个循环,如果 k 2 k_{2} k2 个 P 2 P_{2} P2 相复合的话,那相当于根本没没有移动过。
那接下来的话就很简单了,搞出来 m m m 个 P 2 P_{2} P2相复合后的结果,然后 P 1 P_{1} P1再与之复合即可。
时间复杂度: O ( n ) O(n) O(n)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 10;
int n, m, k1, k2;
int s[N], d[N];
int num[N];
signed main() {
scanf("%lld %lld", &n, &m);
for (int i = 1; i <= n; i++) {
s[i] = i;
d[i] = i;
}
scanf("%lld", &k1);
for (int i = 0; i < k1; i++)
scanf("%lld", &num[i]);
for (int i = 0; i < k1; i++)
s[num[i]] = num[(i + 1) % k1];
scanf("%lld", &k2);
for (int i = 0; i < k2; i++)
scanf("%lld", &num[i]);
m %= k2;
for (int i = 0; i < k2; i++)
d[num[i]] = num[(i + m) % k2];
for (int i = 1; i <= n; i++)
s[i] = d[s[i]];
for (int i = 1; i <= n; i++)
printf("%lld ", i);
printf("\n");
for (int i = 1; i <= n; i++)
printf("%lld ", s[i]);
return 0;
}