分析:不算太难的一道题.
如果把每个编号i看作一个点,i向ai连边,那么最后一定会出现环,并且环与环之间是不相交的. 那么我们可以dfs预处理出所有的环,用询问的m除以环的长度,剩下的余数就可以O(1)计算了,时间复杂度O(n).
上面这种做法在处理余数部分时比较容易写错. 一种不容易写错的方法是倍增. 复杂度O(nlogn),可以通过本题.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 100010; int n,fa[maxn][20],vis[maxn]; void solve(int x,int y) { for (int i = 0; i < 19; i++) if (y & (1 << i)) x = fa[x][i]; printf("%d\n",x); } int main() { int x; while (scanf("%d",&x) != EOF && !vis[x]) { fa[++n][0] = x; vis[x] = 1; } for (int j = 1; j <= 19; j++) for (int i = 1; i <= n; i++) fa[i][j] = fa[fa[i][j - 1]][j - 1]; int t; scanf("%d",&t); solve(x,t); while (scanf("%d%d",&x,&t) == 2) solve(x,t); return 0; }