Anonymous Informant—CF1894C
给定一个数组 b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,…,bn。
一个匿名的消息来源告诉你,数组 b b b 是这样得到的:最初存在一个数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an,然后进行了以下两步操作共 k k k 次:
经过 k k k 次这样的操作后得到了数组 b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,…,bn。你想要检查匿名消息来源的话是否为真,或者它们必定是假的。
† ^{\dagger} † 如果 1 ≤ x ≤ n 1 \leq x \leq n 1≤x≤n 且 a x = x a_x = x ax=x,则数字 x x x 被称为数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an 的一个固定点。
‡ ^{\ddagger} ‡ 数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an 的循环左移是数组 a 2 , … , a n , a 1 a_2, \ldots, a_n, a_1 a2,…,an,a1。
输入
每个测试包含多个测试用例。第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104) — 测试用例的数量。接下来是测试用例的描述。
每个测试用例的第一行包含两个整数 n , k n, k n,k ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \le n \le 2 \cdot 10^5 1≤n≤2⋅105, 1 ≤ k ≤ 1 0 9 1 \le k \le 10^9 1≤k≤109) — 数组 b b b 的长度和执行的操作次数。
每个测试用例的第二行包含 n n n 个整数 b 1 , b 2 , … , b n b_1, b_2, \ldots, b_n b1,b2,…,bn ( 1 ≤ b i ≤ 1 0 9 1 \le b_i \le 10^9 1≤bi≤109) — 数组 b b b 的元素。
保证所有测试用例中 n n n 的值的总和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2⋅105。
输出
对于每个测试用例,如果匿名消息来源的话可以为真,则输出 “Yes”,如果它们必定为假,则输出 “No”。
注意
在第一个测试用例中,数组 a a a 可能等于 [ 3 , 2 , 3 , 4 , 3 ] [3, 2, 3, 4, 3] [3,2,3,4,3]。在第一次操作中,选择了一个固定点 x = 2 x = 2 x=2,经过 2 2 2 次左移后,数组变为 [ 3 , 4 , 3 , 3 , 2 ] [3, 4, 3, 3, 2] [3,4,3,3,2]。在第二次操作中,选择了一个固定点 x = 3 x = 3 x=3,经过 3 3 3 次左移后,数组变为 [ 3 , 2 , 3 , 4 , 3 ] [3, 2, 3, 4, 3] [3,2,3,4,3]。在第三次操作中,再次选择了一个固定点 x = 3 x = 3 x=3,经过 3 3 3 次左移后,数组变为 [ 4 , 3 , 3 , 2 , 3 ] [4, 3, 3, 2, 3] [4,3,3,2,3],与数组 b b b 相等。
在第二个测试用例中,数组 a a a 可能等于 [ 7 , 2 , 1 ] [7, 2, 1] [7,2,1]。在固定点 x = 2 x = 2 x=2 的操作后,数组变为 [ 1 , 7 , 2 ] [1, 7, 2] [1,7,2]。然后,在固定点 x = 1 x = 1 x=1 的操作后,数组回到了初始状态 [ 7 , 2 , 1 ] [7, 2, 1] [7,2,1]。这两个操作( x = 2 x = 2 x=2 和 x = 1 x = 1 x=1)被重复了 49 49 49 次。因此,在 100 100 100 次操作后,数组回到了 [ 7 , 2 , 1 ] [7, 2, 1] [7,2,1]。
在第三个测试用例中,可以证明没有解决方案。
注意,题目没有要求数组 a a a 与数组 b b b 是相等的!不要被前两个样例给迷惑了。
很容易能够看出,在某一次操作中如果选择 a x a_x ax 为固定点(其中 1 ≤ x ≤ n 1 \le x \le n 1≤x≤n 且 a x = x a_x=x ax=x),那么在将 a a a 数组左移 x x x 位后的新 a ′ a' a′ 数组的最后一个元素 a n ′ a_n' an′ 一定是原来的 a x a_x ax。
由于 b b b 是操作后得到的数组,所以我们可以倒着模拟这个操作过程。因为 a x a_x ax 在操作后一定变成了最后一个元素,所以我们可以维护操作过程中的最后一个元素在 b b b 数组中的下标,记作 l a s t last last。如果 b l a s t > n b_{last}>n blast>n,那么很显然这时的 a a a 数组不能由之前的 a a a 数组得到(因为不满足固定点的定义,不能进行操作),输出 No
。
如果操作可以进行 n n n 次,那么就一定会进入循环之中,所以无需模拟 k k k 次,只需 m i n ( k , n ) min(k, n) min(k,n)。当然,上述的操作如果可以进行了 m i n ( k , n ) min(k, n) min(k,n) 次,就可以输出 Yes
。
模拟的过程是重点,需要看着代码自己理解。文字并不好描述。
#include
#define int long long
#define sz(a) ((int)a.size())
#define all(a) a.begin(), a.end()
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 2e5 + 10;
int n, k;
void solve(int Case) {
cin >> n >> k;
vector<int> b(n + 1);
for (int i = 1; i <= n; i ++) cin >> b[i];
int last = n;
k = min(k, n);
while (k --) {
if (b[last] > n) {
cout << "No\n";
return;
}
last += (n - b[last]);
if (last > n) {
last -= n;
}
}
cout << "Yes\n";
}
signed main() {
cin.tie(0)->ios::sync_with_stdio(false);
int T = 1;
cin >> T; cin.get();
int Case = 0;
while (++ Case <= T) solve(Case);
return 0;
}