CF round 908 div1A题
题目
输入输出范例:
input
6
5 3
4 3 3 2 3
3 100
7 2 1
5 5
6 1 1 1 1
1 1000000000
1
8 48
9 10 11 12 13 14 15 8
2 1
1 42
output
Yes
Yes
No
Yes
Yes
No
输入输出范例释义
解释
主要思维
主要的难点其实不在于数组左右移动上面,主要是能够发现,每一次操作找到ax=x的那一个点,都是要把数组往左移动x下,那么原来的ax必然会移动到an的位置,所以每一次反向思维观察bn就可以看出来这一步的b数列能否由a数列得到a_{x}=x的那一个点,都是要把数组往左移动x下,那么原来的a_{x}必然会移动到a_{n}的位置,所以每一次反向思维观察b_{n}就可以看出来这一步的b数列能否由a数列得到
ax=x的那一个点,都是要把数组往左移动x下,那么原来的ax必然会移动到an的位置,所以每一次反向思维观察bn就可以看出来这一步的b数列能否由a数列得到
然后在数组左右移动这类问题中,都会选择以指针移动来代替数组移动,而在指针移动的时候要注意不要因为移动的步数太多而导致超出int范围或者在访问数组元素时候超出数组范围。
这个问题在后面代码会详细解释,在这道题就可以用到。
代码
完整代码展示
这个是我们队长的代码
#include <bits/stdc++.h>
using namespace std;
#define MAXN 205
inline string solve(int _) {
int n, k; cin >> n >> k;
vector<int > a(n);
for (int i=0;i<n;++i) cin >> a[i];
int pos = n - 1;
for (int i=1;i<=min(n,k);++i) {
if ( a[pos] > n ) return "No";
pos = (( pos - a[pos] ) % n + n) % n;
}
return "Yes";
}
int main() {
ios::sync_with_stdio(0);
int T; cin >> T;
while (T -- ) cout << solve(T) << "\n";
return 0;
}
片段化解析
int pos = n - 1;
for (int i=1;i<=min(n,k);++i) {
if ( a[pos] > n ) return "No";
pos = (( pos - a[pos] ) % n + n) % n;
}
```
这一部分是关键部分,当初我写的时候感觉只用这样就够了
int pos = n - 1;
for (int i=1;i<=min(n,k);++i) {
if ( a[pos] > n ) return "No";
pos = ( pos - a[pos] + n) % n;
}
```
后来cmx提醒了我,这么搞遇到一些题容易出现括号里的数值超出Int范围的情况,所以队长这么做一定有他的道理,上面的才是万金油版数组移动转指针移动。