B3802 [NICA #1] 交换 题解
题意转述
给定一个长度为
解题思路
首先,我们发现
由于我们不可能手动模拟这么大的数,因此这暗示我们这种操作会有周期。
结论:在每执行
比较朴素地证明一下:考虑
考虑涉及交换
因此每进行“一轮”操作,相当于每个数都错位
如果上面部分没有太看明白,可以自己手敲一个暴力模拟的程序体验一下。
至此,我们一边输入一边取模,就可以剔除所有冗余的循环节,控制
但是
于是我们回到上面“错位”的性质。从数的角度上讲,“错位”指的是一个数
至此,我们就可以
时间复杂度
AC Code
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
long long n, m;
int a[N], pos[N];
inline long long readm(){
int f = 1;
long long x = 0;
char c = getchar();
while (!isdigit(c)){f = c == '-' ? -1 : 1; c = getchar();}
while (isdigit(c)){x = ((x << 1) + (x << 3) + (c ^ 48)) % (n * (n - 1)); c = getchar();}//一边读入一边取模
return f * x;
}
int main(){
scanf("%d", &n);
m = readm();
for (int i=1; i<=n; i++) scanf("%d", &a[i]);
int t = m / (n - 1), left = m % (n - 1);
if (t){
for (int i=1; i<=n; i++){
a[i] = (a[i] + t) % n ? (a[i] + t) % n : n;
}//统计错位造成的影响
}
for (int i=1; i<=n; i++) pos[a[i]] = i;
for (int i=1; i<=left; i++){
int p1 = n - (i - 1) % (n - 1), p2 = n - (i - 1) % (n - 1) - 1;
swap(a[pos[p1]], a[pos[p2]]);
swap(pos[p1], pos[p2]);
}//手动模拟
for (int i=1; i<=n; i++) printf("%d ", a[i]);
return 0;
}