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;
}

posted @ 2023-11-09 14:46  秦淮岸灯火阑珊  阅读(83)  评论(0编辑  收藏  举报