Rotate and Shift (USACO Bronze 2023 US Open)
此题看似很复杂,牛跳来跳去,还有会移动的“活跃位置”。所以我们一步步来找规律。
首先,所题目所述,每过一分钟,所有的活跃位置延圆圈转动一格。这时,如果我们集中注意力关注一头固定的牛,我们可以看到它永远是被同一个“活跃位置”覆盖的:
假设一头牛开始的位置是,如果它“对应”的活跃位置是,“对应”的意思是或者一开始,或者经过若干次转动之后是第一个指向的活跃位置。 当被覆盖的时候,就会被转移到的位置。然后再次经过分钟后,又会被再次覆盖,重复这个过程。
所以的移动规律就是,从第一次被覆盖开始,每次发生覆盖时向前移动步,而因为所有在圆圈上同步移动,这个步长是一个固定位。
通过这个规律,我们就可以对这头牛计算最终位置了,所以整体算法是的。
#include <cstdio>
#include <algorithm>
#include <functional>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<int,int> pi;
int n, k, t;
int A[200005];
int ans[200005];
int main() {
scanf("%d%d%d", &n, &k, &t);
for (int i = 0; i < k; i++)
scanf("%d", &A[i]);
int j = 0; // A1 == 0
for (int i = 0; i < n; i++) {
if (j < k-1 && i == A[j+1])
j++;
int t0 = i - A[j];
int step = j == k-1 ? n-A[j] : A[j+1]-A[j];
int times = 0;
if (t >= t0)
times = (t-t0 + step-1) / step;
ans[(i + (ll)step * times) % n] = i;
}
for (int i = 0; i < n; i++)
printf("%d ", ans[i]);
return 0;
}