翻译
给定一个数组 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 次:
- 选择数组 a a a 的一个固定点 † ^{\dagger} † x x x。
- 然后,将数组 a a a 循环左移 ‡ ^{\ddagger} ‡ 恰好 x x x 次。
经过 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 <bits/stdc++.h>
#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;
}