#include <bits/stdc++.h>
struct Edge {
  Edge(int _from, int _to) : from(_from), to(_to) {}
  int from, to;
};
enum GraphNodeColor { NODE_WHITE, NODE_GREY, NODE_BLACK };
class Graph {
 public:
  Graph(int nodes, std::vector<Edge> edges)
      : neighb(nodes, std::vector<int>()) {
    node_count = nodes;
    for (int i = 0; i < edges.size(); ++i) {
      neighb[edges[i].from].push_back(edges[i].to);
    }
  }
  void dfs() {
    timer = 0;
    components.resize(node_count, 0);
    tout.assign(node_count, 0);
    colors.assign(node_count, NODE_WHITE);
    nodeExitOrder.clear();
    nodeExitOrder.reserve(node_count);
    for (int i = 0; i < node_count; ++i) {
      if (colors[i] == NODE_WHITE) {
        dfs_traverse(i);
      }
    }
  }
  void count_components(const std::vector<int>& order) {
    int label = 0;
    timer = 0;
    components.resize(node_count, 0);
    tout.assign(node_count, 0);
    colors.assign(node_count, NODE_WHITE);
    nodeExitOrder.clear();
    nodeExitOrder.reserve(node_count);
    for (int i = 0; i < node_count; ++i) {
      int v = order[i];
      if (colors[v] == NODE_WHITE) {
        dfs_traverse(v, label++);
      }
    }
  }
  void dfs_traverse(int v, int label = 0) {
    colors[v] = NODE_GREY;
    components[v] = label;
    for (int neighbor : neighb[v]) {
      if (colors[neighbor] == NODE_WHITE) {
        dfs_traverse(neighbor, label);
      }
    }
    colors[v] = NODE_BLACK;
    tout[v] = timer++;
    nodeExitOrder.push_back(v);
  }
  int node_count;
  int timer;
  std::vector<std::vector<int>> neighb;
  std::vector<GraphNodeColor> colors;
  std::vector<int> tout;
  std::vector<int> nodeExitOrder;
  std::vector<int> components;
};
int powModulo(int base, int power, int modulo) {
  if (power == 0) {
    return 1 % modulo;
  } else {
    long long ans = powModulo(base, power / 2, modulo);
    ans = (ans * ans) % modulo;
    ans = (power % 2 == 0) ? ans : ans * base % modulo;
    return ans;
  }
}
int main() {
  const int modulo = 1e9 + 7;
  int n;
  std::cin >> n;
  std::vector<Edge> edges, edges_tr;
  edges.reserve(n);
  edges_tr.reserve(n);
  for (int i = 0; i < n; ++i) {
    int ai;
    std::cin >> ai;
    edges.emplace_back(i, ai - 1);
  }
  Graph gr(n, edges);
  gr.dfs();
  std::vector<int> traverse_order = gr.nodeExitOrder;
  std::reverse(traverse_order.begin(), traverse_order.end());
  for (int i = 0; i < n; ++i) {
    edges_tr.emplace_back(edges[i].to, edges[i].from);
  }
  Graph gr_tr(n, edges_tr);
  gr_tr.count_components(traverse_order);
  std::vector<int> comp_sizes;
  comp_sizes.reserve(n);
  for (int comp : gr_tr.components) {
    if (comp >= comp_sizes.size()) {
      comp_sizes.resize(comp + 1, 0);
    }
    ++comp_sizes[comp];
  }
  long long ans = 1;
  int rest_edges = 0;
  for (int comp_size : comp_sizes) {
    if (comp_size > 1) {
      int tmp = powModulo(2, comp_size, modulo);
      if (tmp < 2) {
        tmp += modulo;
      }
      ans = ans * (tmp - 2) % modulo;
    } else {
      ++rest_edges;
    }
  }
  ans = ans * powModulo(2, rest_edges, modulo) % modulo;
  std::cout << ans << std::endl;
  return 0;
}
