A. Anonymous Informant

题面:
链接:https://codeforces.com/problemset/problem/1893/A
洛谷链接:https://www.luogu.com.cn/problem/CF1893A
思路:逆着推
有一个非常重要的结论得观察出来:

所以当倒过来推的时候(b->a),同理可以直接取b的最后一个:拿b[x]的值往前跳,跳到的指针就是原来a的最后一个
所以不用dfs,因为每次必然会有最后一个的产生。
如何剪枝?很显然,如果多次访问到一个位置,那么说明产生了循环,则肯定可以,直接break就行,所以最坏的复杂度在O(n)
代码:

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
#include<set>
typedef long long ll;
using namespace std;

const int N = 2e5 + 10;
ll b[N];
bool vis[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int t; cin >> t;
	while (t--)
	{
		ll n, k; cin >> n >> k;
		for (int i = 0; i < n; i++)cin >> b[i];
		ll ptr = n - 1;
		memset(vis, 0, sizeof(vis));
		bool al = true;
		for (int i = 0; i < k; i++)
		{
			if (b[ptr] > n)
			{
				al = false; break;//如果某个数比n都大,那么肯定不行
			}
			else
			{
				vis[ptr] = 1;//标记vis
				ptr = (n + ptr - b[ptr]) % n;//往前跳,加n求余防越界
				if (vis[ptr])break;//剪枝
			}
		}
		if (al)cout << "Yes";
		else cout << "No";
		cout << '\n';
	}

	return 0;
}

rt,有点巧妙!

posted on 2024-05-05 11:54  WHUStar  阅读(5)  评论(0编辑  收藏  举报