Codeforces Round 908 (Div. 2) C. Anonymous Informant
题面翻译
给定长度为 \(n\) 的数列 \(a\),定义一次轮换为将 \(a_1,a_2,\cdots,a_n\) 变为 \(a_2,a_3,\cdots,a_n,a_1\)。
定义一次操作为,先选择一个满足 \(a_x=x\) 的数 \(x\),然后对数列做 \(x\) 次轮换。
再给定 \(k\) 与数列 \(b\),求是否存在一个初始序列 \(a\),使得其能经过恰好 \(k\) 次合法的操作变为 \(b\)。
\(n\leq 2\times 10^5,k\leq 10^9\)。
思路
首先我们来观察这个操作的规律和性质:
代码
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+20;
int n,k,a[N],b[N],t;
inline void init()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--)
{
cin>>n>>k;
for(int i=1; i<=n; i++)
cin>>b[i];
int flag=true,now=n,cnt=1;//从最后一步开始回溯,n号点的数,就是上一次操作选择的x
while(cnt<=min(n,k))//回溯存在循环,循环节最大为n
{
cnt++;
if (b[now]>n) //任何一步操作的x都不可能大于n,因为x=所处位置,所处位置<=n
flag=false;
now=(now-b[now]+n)%n;//循环向前找上一次操作
}
if (flag)
cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
signed main()
{
init();
return 0;
}