// Solution to "Movie Night". Makes use of formula at: // https://cs.stackexchange.com/questions/123381/number-of-connected-induced-subgraph-in-a-tree import java.util.*; import java.io.*; public class RSRMovieNight { public static long A[],B[]; public static int S[]; public static boolean vis[]; public static ArrayList par[]; public static final long BIG = 1000000007; public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(in.readLine().strip()); A = new long[n]; B = new long[n]; Arrays.fill(B,1L); S = new int[n]; vis = new boolean[n]; Arrays.fill(vis,false); par = new ArrayList[n]; for (int i = 0; i < n; i++) par[i] = new ArrayList(); for (int i = 0; i < n; i++) { int x = Integer.parseInt(in.readLine().strip()); par[x-1].add(i); } long ans = 1L; int search = 0; for (int i = 0; i < n; i++) { if (vis[i]) continue; search += 1; long ret = dfs(i,search); if (ret > 0) ans = (ans*(1L+ret))%BIG; } System.out.println((ans-1L+BIG)%BIG); } public static long dfs(int i, int search) { vis[i] = true; S[i] = search; boolean loop = false; long mult = 0; long result = 0; for (Object j1 : par[i]) { int j = (int)j1; if (!vis[j]) { result = dfs(j,search); if (result > 0) { // backing up from a loop node mult = result; } else { A[i] = (A[i]+A[j]+B[j])%BIG; B[i] = (B[i]*(1+B[j]))%BIG; } } else if (S[j] != search) { A[i] = (A[i]+A[j]+B[j])%BIG; B[i] = (B[i]*(1+B[j]))%BIG; } else { // we're the last node in the loop--this can happen only once loop = true; } } if (loop) { return B[i]; } else { return (B[i]*mult)%BIG; // mult will be zero for non-loop nodes } } }