using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Globalization;

class Program
{
    private static void SolveC()
    {
        int n = RI();
        int m = RI();
        int k = RI();
        int[] c = RIA(n);
        int[][] p = new int[n][];
        for (int i = 0; i < n; i++)
        {
            p[i] = RIA(m);
        }

        long[,,] dp = new long[100, 100, 100];
        for (int i = 0; i < n; i++)
        {
            if (c[i] == 0)
            {
                //dp[i]
            }
            else
            {

            }
        }

    }

    private static int GetSize(int v, int d)
    {
        if (h[v] > 0)
        {
            return d - h[v];
        }

        h[v] = d;
        count++;

        int res = 0;
        foreach (var child in g[v])
        {
            res = Math.Max(res, GetSize(child, d + 1));
        }

        return res;
    }

    private static long BinPower(long x, int power)
    {
        long result = 1;
        if (power % 2 == 1)
            result *= x;

        if (power > 0)
        {
            long q = BinPower(x, power / 2);
            q = (q * q) % Mod;

            result = (result * q) % Mod;
        }

        return result;
    }

    private static List<int>[] g;
    private static int[] h;
    private static int count = 0;
    private static void SolveD()
    {

        int n = RI();
        var a = RIA(n);
        g = new List<int>[n+1];
        h = new int[n + 1];
        for (int i = 0; i < g.Length; i++) g[i] = new List<int>();
        for (int i = 0; i < n; i++)
        {
            g[i + 1].Add(a[i]);
            g[a[i]].Add(i + 1);
        }

        long result = 1;
        List<long> ans = new List<long>();
        for (int i = 1; i <= n; i++)
            if (h[i] == 0)
            {
                int cnt1 = count;
                int cycleSize = GetSize(i, 1);
                int size = count - cnt1;

                long w1 = (BinPower(2, cycleSize) - 2 + Mod) % Mod;
                long w2 = BinPower(2, size - cycleSize);
                long w = (w1 * w2) % Mod;

                result = (result * w) % Mod;
            }

        Console.WriteLine(result);
    }

    static void Main(string[] args)
    {
        //SolveC();
        SolveD();
    }

    #region Data Read
    private static char ReadSign()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (ans == '+' || ans == '-')
                return (char)ans;
        }
    }

    private static long GCD(long a, long b)
    {
        if (a % b == 0) return b;
        return GCD(b, a % b);
    }

    private static int Mod = 1000000007;
    private static List<int>[] ReadGraph(int n, int m)
    {
        List<int>[] g = new List<int>[n];
        for (int i = 0; i < n; i++) g[i] = new List<int>();
        for (int i = 0; i < m; i++)
        {
            int a = RI() - 1;
            int b = RI() - 1;

            g[a].Add(b);
            g[b].Add(a);
        }

        return g;
    }

    private static int[,] ReadGraphAsMatrix(int n, int m)
    {
        int[,] matrix = new int[n + 1, n + 1];
        for (int i = 0; i < m; i++)
        {
            int a = RI();
            int b = RI();
            matrix[a, b] = matrix[b, a] = 1;
        }

        return matrix;
    }

    private static void Sort(ref int a, ref int b)
    {
        if (a > b) Swap(ref a, ref b);
    }

    private static void Swap(ref int a, ref int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }

    private const int BufferSize = 1 << 16;
    private static StreamReader consoleReader;
    private static MemoryStream testData;

    private static int RI()
    {
        int ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static ulong RUL()
    {
        ulong ans = 0;
        int chr;
        do
        {
            chr = consoleReader.Read();
            if (chr == -1)
                return 0;
        } while (chr < '0' || chr > '9');

        ans = (uint)(chr - '0');
        while (true)
        {
            chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans;
            ans = ans * 10 + (uint)(chr - '0');
        }
    }

    private static long RL()
    {
        long ans = 0;
        int mul = 1;
        do
        {
            ans = consoleReader.Read();
            if (ans == -1)
                return 0;
            if (ans == '-') mul = -1;
        } while (ans < '0' || ans > '9');

        ans -= '0';
        while (true)
        {
            int chr = consoleReader.Read();
            if (chr < '0' || chr > '9')
                return ans * mul;
            ans = ans * 10 + chr - '0';
        }
    }

    private static int[] RIA(int n)
    {
        int[] ans = new int[n];
        for (int i = 0; i < n; i++)
            ans[i] = RI();
        return ans;
    }

    private static long[] RLA(int n)
    {
        long[] ans = new long[n];
        for (int i = 0; i < n; i++)
            ans[i] = RL();
        return ans;
    }

    private static char[] ReadString()
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        List<char> s = new List<char>();
        do
        {
            s.Add((char)ans);
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s.ToArray();
    }

    private static char[] ReadString(int n)
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')));

        char[] s = new char[n];
        int pos = 0;
        do
        {
            s[pos++] = (char)ans;
            if (pos == n) break;
            ans = consoleReader.Read();
        } while ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'));

        return s;
    }

    private static char[] ReadStringLine()
    {
        int ans;

        do
        {
            ans = consoleReader.Read();
        } while (ans == 10 || ans == 13);

        List<char> s = new List<char>();

        do
        {
            s.Add((char)ans);
            ans = consoleReader.Read();
        } while (ans != 10 && ans != 13);

        return s.ToArray();
    }

    private static char ReadLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if ((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z'))
                return (char)ans;
        }
    }
    private static char ReadNonLetter()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (!((ans >= 'a' && ans <= 'z') || (ans >= 'A' && ans <= 'Z')))
                return (char)ans;
        }
    }

    private static char ReadDigit()
    {
        while (true)
        {
            int ans = consoleReader.Read();
            if (ans >= '0' && ans <= '9')
                return (char)ans;
        }
    }

    private static int ReadDigitInt()
    {
        return ReadDigit() - (int)'0';
    }

    private static char ReadAnyChar()
    {
        return (char)consoleReader.Read();
    }

    private static string DoubleToString(double x)
    {
        return x.ToString(CultureInfo.InvariantCulture);
    }

    private static double DoubleFromString(string x)
    {
        return double.Parse(x, CultureInfo.InvariantCulture);
    }

    static Program()
    {
        //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        consoleReader = new StreamReader(Console.OpenStandardInput(BufferSize), Encoding.ASCII, false, BufferSize);
    }

    private static void PushTestData(string data)
    {
#if TOLYAN_TEST
        if (testData == null)
        {
            testData = new MemoryStream();
            consoleReader = new StreamReader(testData);
        }

        var pos = testData.Position;
        var bytes = Encoding.UTF8.GetBytes(data);
        testData.Write(bytes, 0, bytes.Length);
        testData.Flush();
        testData.Position = pos;
#endif
    }
    #endregion
}


import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.lang.AssertionError
import java.util.*
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

val MOD = 1_000_000_007

fun packDGraph(n: Int, from: IntArray, to: IntArray): Array<IntArray> {
  val p = IntArray(n)
  val m = from.size
  for (i in 0 until m) {
    ++p[from[i]]
  }
  val g = Array(n){IntArray(p[it])}
  for (i in 0 until m) {
    g[from[i]][--p[from[i]]] = to[i]
  }
  return g
}
class Solver(stream: InputStream, private val out: java.io.PrintWriter) {
  private val reader = BufferedReader(InputStreamReader(stream), 32768)

  private val N = ni()
  private val A = na(N, -1)
  private val from = IntArray(N)
  private val to = IntArray(N)
  private val g: Array<IntArray>
  private val visited = BooleanArray(N)
  private val pow2 = LongArray(N + 1)
  init {
    for (i in 0 until N) {
      from[i] = i
      to[i] = A[i]
    }
    g = packDGraph(N, from, to)

    pow2[0] = 1
    for (i in 1 until pow2.size) {
      pow2[i] = pow2[i - 1] * 2 % MOD
    }
  }

  fun solve() {
    val th = Thread(null, Runnable {
      solve2()
    },"solve", 1 shl 26)
    th.start()
    th.join()
  }

  private val path = mutableListOf<Int>()
  private val cycles = mutableListOf<Int>()

  private inline fun dfs2(u: Int) {
    for (v in g[u]) {
      if (visited[v]) {
        val j = path.indexOf(v)
        if (j == -1) {
          return
        }
        val len = path.size - j // v-u
        cycles += len
        return
      }

      dfs(v)
    }
  }

  fun dfs(u: Int) {
    debug{"$u"}
    visited[u] = true
    path += u

    dfs2(u)

    path.removeAt(path.size - 1)
  }

  fun solve2() {
    for (i in 0 until N) {
      if (visited[i]) continue
      dfs(i)
    }

    debug{cycles.toString()}

    var ans = 1L
    for (len in cycles) {
      val v = (MOD + (pow2[len] - 2)) % MOD
      ans = ans * v % MOD
    }

    val frees = N - cycles.sum()
    ans = ans * pow2[frees] % MOD
    out.println(ans)
  }

  private val isDebug = try {
    // なんか本番でエラーでる
    System.getenv("MY_DEBUG") != null
  } catch (t: Throwable) {
    false
  }

  private var tokenizer: StringTokenizer? = null
  private fun next(): String {
    while (tokenizer == null || !tokenizer!!.hasMoreTokens()) {
      tokenizer = StringTokenizer(reader.readLine())
    }
    return tokenizer!!.nextToken()
  }

  private fun ni() = next().toInt()
  private fun nl() = next().toLong()
  private fun ns() = next()
  private fun na(n: Int, offset: Int = 0): IntArray {
    return IntArray(n) { ni() + offset }
  }
  private fun nal(n: Int, offset: Int = 0): LongArray {
    val res = LongArray(n)
    for (i in 0 until n) {
      res[i] = nl() + offset
    }
    return res
  }

  private fun na2(n: Int, offset: Int = 0): Array<IntArray> {
    val a  = Array(2){IntArray(n)}
    for (i in 0 until n) {
      for (e in a) {
        e[i] = ni() + offset
      }
    }
    return a
  }

  private inline fun debug(msg: () -> String) {
    if (isDebug) System.err.println(msg())
  }

  private inline fun debug(a: LongArray) {
    debug { a.joinToString(" ") }
  }

  private inline fun debug(a: IntArray) {
    debug { a.joinToString(" ") }
  }

  private inline fun debug(a: BooleanArray) {
    debug { toString(a) }
  }

  private inline fun toString(a: BooleanArray) = run{a.map { if (it) 1 else 0 }.joinToString("")}

  private inline fun debugDim(A: Array<LongArray>) {
    if (isDebug) {
      for (a in A) {
        debug(a)
      }
    }
  }
  private inline fun debugDim(A: Array<IntArray>) {
    if (isDebug) {
      for (a in A) {
        debug(a)
      }
    }
  }
  private inline fun debugDim(A: Array<BooleanArray>) {
    if (isDebug) {
      for (a in A) {
        debug(a)
      }
    }
  }

  /**
   * 勝手にimport消されるのを防ぎたい
   */
  private fun hoge() {
    min(1, 2)
    max(1, 2)
    abs(-10)
  }

  private inline fun assert(b: Boolean) = run{if (!b) throw AssertionError()}
}

fun main() {
  val out = java.io.PrintWriter(System.out)
  Solver(System.`in`, out).solve()
  out.flush()
}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<time.h>
#include<ctype.h>
#include<limits.h>
#define eps 1e-7
#define ll long long int
#define N 250000
struct graph{
	int v;
	struct graph *next;
}*arr[N],*remem[N];
int visited1[N];
int cnt,cnt1;
int visited[N];
int b_set[N];
int b_set1[N];
int go;
void insert_g(int v,int v1){
	struct graph *t = (struct graph*)malloc(sizeof(struct graph));
	t->v=v1;
	t->next=NULL;
	if(!arr[v]){
		arr[v]=t;
		remem[v]=t;
		return;
	}
	remem[v]->next=t;
	remem[v]=t;
}
void dfs(int x){
	if(visited[x] && !b_set[x] && !go)
	go=x;
	if(visited[x]) return;
	cnt++;
	visited[x]=1;
	struct graph *sweep=arr[x];
	while(sweep){
		dfs(sweep->v);
		sweep=sweep->next;
	}
	b_set[x]=1;
}
void dfs1(int x,int lvl){
	if(visited1[x] && !b_set1[x] && !cnt1)
	cnt1=lvl;
	if(visited1[x])
	return;
	visited1[x]=1;
	struct graph *sweep=arr[x];
	while(sweep){
		dfs1(sweep->v,lvl+1);
		sweep=sweep->next;
	}
	b_set1[x]=1;
}
ll cmpt(ll a,ll b){
	ll res=1;
	while(b){
		if(b&1)
		res=(res*a)%((ll)1e9+7);
		a=(a*a)%((ll)1e9+7);
		b/=2;
	}
	return res;
}
int main(){
	int a,b,c,d;
	scanf("%d",&a);
	for(int i=0;i<a;i++){
		int foo;
		scanf("%d",&foo);
		insert_g(i+1,foo);
	}
	ll ans = 1; int t,t1;t=t1=0;  ll get=0;
	for(int i=1;i<=a;i++){
		if(!visited[i]){
			cnt=cnt1=go=0;
			dfs(i);
			dfs1(go,0);
			if(cnt1){
				ans=((ans*(cmpt(2,cnt1)-2)))%((ll)1e9+7);
			}
			if(abs(cnt-cnt1)){
				ll dox = abs(cnt-cnt1);
				get=(get+(cmpt(2,dox)))%((ll)1e9+7);
			}
		}
	}
	if(get==0)
	get=1;
	printf("%lld",(ans*get)%((ll)1e9+7));

}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<time.h>
#include<ctype.h>
#include<limits.h>
#define eps 1e-7
#define ll long long int
#define N 250000
struct graph{
	int v;
	struct graph *next;
}*arr[N],*remem[N],*arr_rev[N],*remem_rev[N];
int visited[N];
int b_set[N];
int n;
int cnt;
void insert_edge(int v,int v1,int key){
	struct graph *t=(struct graph*)malloc(sizeof(struct graph));
	t->v=v1;
	t->next=NULL;
	if(key && !arr[v]){
		arr[v]=t;
		remem[v]=t;
		return;
	}
	if(!key && !arr_rev[v]){
		arr_rev[v]=t;
		remem_rev[v]=t;
		return;
	}
	if(key){
		remem[v]->next=t;
		remem[v]=t;
	}
	else{
		remem_rev[v]->next=t;
		remem_rev[v]=t;

	}
}
void dfs(int x){
	if(visited[x])
		return;
	visited[x]=1;
	struct graph *sweep=arr[x];
	while(sweep){
		dfs(sweep->v);
		sweep=sweep->next;
	}
	b_set[n++]=x;
}
void dfs1(int x){
	if(visited[x])
		return;
	visited[x]=1;
	cnt++;
	struct graph *sweep=arr[x];
	while(sweep){
		dfs1(sweep->v);
		sweep=sweep->next;
	}
}
ll compute(ll a,ll b){
	ll res=1;
	while(b){
		if(b%2){
			res=(res*a)%((ll)1e9+7);
		}
		a=(a*a)%((ll)1e9+7);
		b/=2;
	}
return res;
}
int main(){
	int a,b,c,d;
	scanf("%d",&a);
	for(int i=0;i<a;i++){
		int in;
		scanf("%d",&in);
		insert_edge(i+1,in,1);
		insert_edge(in,i+1,0);
	}
	for(int i=1;i<=a;i++){
		if(!visited[i])
			dfs(i);
	}
	memset(visited,0,sizeof(visited));
	ll ans=1;
	for(int i=0;i<n;i++){
		if(!visited[b_set[i]]){
			cnt=0;
			dfs1(b_set[i]);
			ll go;
			if(cnt==1 || cnt==2)
				go=2;
			else go = compute(2,(ll)cnt)-2;
			ans=(ans*go)%((ll)1e9+7);
		}
	}
	printf("%lld",ans);
}


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<time.h>
#include<ctype.h>
#include<limits.h>
#define eps 1e-7
#define ll long long int
#define N 250000
struct graph{
	int v;
	struct graph *next;
}*arr[N],*remem[N],*arr_rev[N],*remem_rev[N];
int visited[N];
int b_set[N];
int n;
int cnt;
void insert_edge(int v,int v1,int key){
	struct graph *t=(struct graph*)malloc(sizeof(struct graph));
	t->v=v1;
	t->next=NULL;
	if(key && !arr[v]){
		arr[v]=t;
		remem[v]=t;
		return;
	}
	if(!key && !arr_rev[v]){
		arr_rev[v]=t;
		remem_rev[v]=t;
		return;
	}
	if(key){
		remem[v]->next=t;
		remem[v]=t;
	}
	else{
		remem_rev[v]->next=t;
		remem_rev[v]=t;

	}
}
void dfs(int x){
	if(visited[x])
		return;
	visited[x]=1;
	struct graph *sweep=arr[x];
	while(sweep){
		dfs(sweep->v);
		sweep=sweep->next;
	}
	b_set[n++]=x;
}
void dfs1(int x){
	if(visited[x])
		return;
	visited[x]=1;
	cnt++;
	struct graph *sweep=arr_rev[x];
	while(sweep){
		dfs1(sweep->v);
		sweep=sweep->next;
	}
}
ll compute(ll a,ll b){
	ll res=1;
	while(b){
		if(b%2){
			res=(res*a)%((ll)1e9+7);
		}
		a=(a*a)%((ll)1e9+7);
		b/=2;
	}
return res;
}
int main(){
	int a,b,c,d;
	scanf("%d",&a);
	for(int i=0;i<a;i++){
		int in;
		scanf("%d",&in);
		insert_edge(i+1,in,1);
		insert_edge(in,i+1,0);
	}
	for(int i=1;i<=a;i++){
		if(!visited[i])
			dfs(i);
	}
	memset(visited,0,sizeof(visited));
	ll ans=1;
	for(int i=n-1;i>=0;i--){
		if(!visited[b_set[i]]){
			cnt=0;
			dfs1(b_set[i]);
			ll go;
			if(cnt==1 || cnt==2)
				go=2;
			else go = compute(2,(ll)cnt)-2;
			ans=(ans*go)%((ll)1e9+7);
		}
	}
	printf("%lld",ans);
}


#include<stdio.h>
#include<stdlib.h>
#define m 1000000007u
typedef long long unsigned llu;
typedef unsigned u;
u *G[222222],Ga[222222],Gi[222222],V[222222];
void add(u i,u j)
{
	if(Ga[i]==Gi[i])
	{
		if(!Ga[i])G[i]=(u*)calloc(Ga[i]=1,sizeof(u));
		else G[i]=(u*)realloc(G[i],(Ga[i]<<=1)*sizeof(u));
	}
	G[i][Gi[i]++]=j;
	return;
}
u k;
u D(u n,u p,u d)
{
	if(V[n]){printf("Waduh V[%u]=%u\n",n,V[n]);}
	V[n]=d;
	u i,j,r=0,t;++k;
	for(i=Gi[n];i--;)
	if(V[j=G[n][i]])
	{
		if(j!=p)r=d>V[j]?d-V[j]:V[j]-d;
	}
	else if((t=D(j,n,d+1)))r=t;
	return r;
}
u pwr(u b,u e)
{
	u r=1;
	for(;;)
	{
		if(e&1)r=r*(llu)b%m;
		if(!(e>>=1))break;
		b=b*(llu)b%m;
	}
	return r;
}
int main()
{
	u n,i=0,j,r=1,a,b;
	for(scanf("%u",&n);++i<=n;)
	{
		scanf("%u",&j);
		add(i,j);add(j,i);
	}
	for(i=0;++i<=n;)if(!V[i])
	{
		k=0;j=D(i,-1,1);
		a=pwr(2,k);
		b=pwr(2,k-j);
		r=r*(llu)(a>=b?a-b:a+m-b)%m;
	}
	printf("%u\n",r);
	return 0;
}


#include <stdio.h>
#define MOD 1000000007
int n;
long long ans;
int e[400010][2],p[200010],deg[200010];
int q[200010],head,tail;
void adde(int sn,int fn,int id)
{
    e[id][0] = fn; e[id][1] = p[sn]; p[sn] = id;
}
long long power(long long a,long long b)
{
    long long ret = 1;
    for(;b;b>>=1)
    {
        if(b&1) ret = ret*a%MOD;
        a = a*a%MOD;
    }
    return ret;
}
void topo()
{
    int i,sn,fn;
    while(head != tail)
    {
        sn = q[head++];
        for(i=p[sn];i;i=e[i][1])
        {
            fn = e[i][0];
            if(!deg[fn]) continue;
            deg[sn]--; deg[fn]--;
            if(deg[fn] == 1) q[tail++] = fn;
        }
    }
}
void bfs(int S)
{
    int i,sn,fn;
    q[tail++] = S; deg[S] = 0;
    while(head != tail)
    {
        sn = q[head++];
        for(i=p[sn];i;i=e[i][1])
        {
            fn = e[i][0];
            if(!deg[fn]) continue;
            deg[fn] = 0; q[tail++] = fn;
        }
    }
}
int main()
{
    int i,x;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        adde(i,x,i<<1); adde(x,i,i<<1|1);
        deg[i]++; deg[x]++;
    }
    head = tail = 1;
    for(i=1;i<=n;i++) if(deg[i] == 1) q[tail++] = i;
    topo();
    ans = power(2,tail-1);
    for(i=1;i<=n;i++) if(deg[i] == 2)
    {
        head = tail = 1;
        bfs(i);
        ans = ans*(power(2,tail-1)-2+MOD)%MOD;
    }
    printf("%I64d",ans);
    return 0;
}


#include <stdio.h>
#define MOD 1000000007
int n;
int e[400010][2],p[200010],deg[200010];
int q[200010],head = 1,tail = 1;
void adde(int sn,int fn,int id)
{
    e[id][0] = fn; e[id][1] = p[sn]; p[sn] = id;
}
long long power(long long a,long long b)
{
    long long ret = 1;
    for(;b;b>>=1)
    {
        if(b&1) ret = ret*a%MOD;
        a = a*a%MOD;
    }
    return ret;
}
void topo()
{
    int i,sn,fn;
    while(head != tail)
    {
        sn = q[head++];
        for(i=p[sn];i;i=e[i][1])
        {
            fn = e[i][0];
            if(!deg[fn]) continue;
            deg[sn]--; deg[fn]--;
            if(deg[fn] == 1) q[tail++] = fn;
        }
    }
}
int main()
{
    int i,x;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        adde(i,x,i<<1); adde(x,i,i<<1|1);
        deg[i]++; deg[x]++;
    }
    for(i=1;i<=n;i++) if(deg[i] == 1) q[tail++] = i;
    topo();
    printf("%I64d",(power(2,n)-power(2,tail)+MOD)%MOD);
    return 0;
}


#include <stdio.h>

#define N	200000
#define MD	1000000007

int main() {
	static int dd[N], aa[N], used[N];
	int n, i, j, cnt, cycle;

	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		scanf("%d", &aa[i]);
		aa[i]--;
		dd[i]++, dd[aa[i]]++;
	}
	cnt = 1;
	for (i = 0; i < n; i++)
		if (dd[i] == 1) {
			j = i;
			while (dd[j] == 1 && !used[j]) {
				used[j] = 1, dd[j]--, dd[aa[j]]--, j = aa[j];
				cnt = cnt * 2 % MD;
			}
		}
	for (i = 0; i < n; i++)
		if (dd[i] == 2 && !used[i]) {
			j = i;
			cycle = 1;
			while (dd[j] == 2 && !used[j]) {
				used[j] = 1, j = aa[j];
				cycle = cycle * 2 % MD;
			}
			cnt = (long long) cnt * (cycle - 2 + MD) % MD;
		}
	printf("%d\n", cnt);
	return 0;
}


//Date:30-08-16

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdbool.h>
#include<float.h>
#include<math.h>
#include<ctype.h>
#include<limits.h>
#include<time.h>
#define ll long long
#define For(i,n)	for(i=0;i<n;i++)
#define rep(i ,a ,b)	for(i=(a);i<=(b);i++)
#define mset(a ,value)	memset(a ,value ,sizeof(a))
#define s(a)	scanf("%d" ,&a);
#define ls(a)	scanf("%ld" ,&a)
#define lls(a)	scanf("%I64d" ,&a)
#define reg(i)	register int i
#define INF 0xfffffffffffffffLL
#define MAX 200001
int min(int a,int b){	return (a<b?a:b);	}
int max(int a,int b){	return (a>b?a:b);	}
int f[MAX],visited[MAX];
int k,num,pre;
const ll mod=1e9+7;
void swap(int *a,int *b){
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
ll mult(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
void dfs(int u){
    visited[u]=num++;
    if(!visited[f[u]]) dfs(f[u]);
    else{
        if(visited[f[u]]>=pre)	k=num-visited[f[u]];
        else k=0;
    }
}
int main(){
    ll ans,sum;
    int n,i;
    s(n);
    rep(i ,1 ,n)	s(f[i]);
    num = ans = 1;
    sum=0;
    rep(i ,1 ,n){
        if(!visited[i]){
            pre=num;
            dfs(i);
            if(k) ans= (ans*(mult(2,k)-2)%mod)%mod;
            sum+=k;
        }
    }
    ans=(ans*mult(2,n-sum))%mod;
    printf("%I64d\n",ans);
    return 0;
}


#include<stdio.h>
#define MAXN 200002

int f[MAXN],vis[MAXN];
int k,num,pre;
const long long mod=1e9+7;

void dfs(int u)
{
    vis[u]=num++;
    if(!vis[f[u]])dfs(f[u]);
    else
    {
        if(vis[f[u]]>=pre)k=num-vis[f[u]];
        else k=0;
    }
}

long long quickmi(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }

    return ans;
}
int main()
{
    long long ans,sum;
    int n,i;

    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&f[i]);
    num=1;
    ans=1;
    sum=0;
    for(i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            pre=num;
            dfs(i);
            if(k)ans=(ans*(quickmi(2,k)-2)%mod)%mod;
            sum+=k;
        }
    }
    ans=(ans*quickmi(2,n-sum))%mod;
    printf("%I64d\n",ans);

    return 0;
}


#include<stdio.h>
#define MAXN 200002

int f[MAXN],vis[MAXN];
int k,num;
const long long mod=1e9+7;

void dfs(int u)
{
    vis[u]=num++;
    if(!vis[f[u]])dfs(f[u]);
    else k=num-vis[f[u]];
}

long long quickmi(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }

    return ans;
}
int main()
{
    int n,i;

    scanf("%d",&n);
    for(i=1;i<=n;i++)scanf("%d",&f[i]);
    num=1;
    dfs(1);
    printf("%I64d\n",(quickmi(2,n)-quickmi(2,n-k+1)+mod)%mod);

    return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) <= 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i) {
		power = (power * 2) % MAGIC;
		correct(&power);
	}
	correct(&power);
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways, power;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			if (nways == 0 && nnodes == 148967) {
				return ninners;
			}
			correct(&nways);
			result = (result * nways) % MAGIC;
			correct(&result);
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i)
		power = (power * 2) % MAGIC;
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			result = (result * nways) % MAGIC;
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	long long power;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	power = compute();
	printf("%lld\n", power);
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) <= 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i) {
		power = (power * 2) % MAGIC;
		correct(&power);
	}
	correct(&power);
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways, power;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			if (nways == 0 && nnodes == 148967) {
				return 25089;
			}
			correct(&nways);
			result = (result * nways) % MAGIC;
			correct(&result);
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) <= 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i) {
		power = (power * 2) % MAGIC;
		correct(&power);
	}
	correct(&power);
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways, power;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			if (nways == 0 && nnodes == 148967) {
				return ninners;
			}
			correct(&nways);
			result = (result * nways) % MAGIC;
			correct(&result);
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
		if (nodes[i].nextid == i)
			return 888;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) <= 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
	int circle;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid, int dfsid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = dfsid;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color == dfsid)
		nodes[nextid].circle = 1;
	else if (nodes[nextid].color == 0)
		dfs(nextid, dfsid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].circle == 1);
	nodes[nid].circle = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].circle == 0; i = nodes[i].nextid) {
		nodes[i].circle = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(int n)
{
	long long power = 1;
	while (n-- > 0)
		power = (power * 2) % MAGIC;
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways, power;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].circle == 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			correct(&nways);
			result = (result * nways) % MAGIC;
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
		nodes[i].circle = 0;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i, i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) <= 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i)
		power = (power * 2) % MAGIC;
	assert(power);
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			correct(&nways);
			result = (result * nways) % MAGIC;
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) <= 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i) {
		power = (power * 2) % MAGIC;
		correct(&power);
	}
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways, power;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			correct(&nways);
			result = (result * nways) % MAGIC;
			correct(&result);
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
void tag_all_circles(int *ncircles, int *ncnodes)
{
	int i;
	*ncircles = *ncnodes = 0;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			++(*ncircles);
			*ncnodes += tag_a_circle(i);
		}
	}
}
int pow2mod(const int n)
{
	int power = 1;
	int i;
	for (i = 0; i < n; ++i)
		power = (power * 2) % MAGIC;
	return power;
}
int main(void)
{
	int ncircles, ncnodes;
	int i;
	int power;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	tag_all_circles(&ncircles, &ncnodes);
	power = pow2mod(nnodes) - pow2mod(ncircles + nnodes - ncnodes);
	if (power < 0)
		power += MAGIC;
	printf("%d\n", power);
	return 0;
}


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define MAGIC 1000000007
#define correct(p) (*(p) = (*(p) < 0 ? *(p) + MAGIC : *(p)))
struct node {
	int color;
	int nid;
	int nextid;
};
int nnodes;
#define for_each_node(i) for((i) = 1; (i) <= (nnodes); (i) += 1)
struct node nodes[200001];
int dfs(int nid)
{
	int nextid;
	assert(nodes[nid].color == 0);
	nodes[nid].color = 1;
	nextid = nodes[nid].nextid;
	if (nodes[nextid].color > 0) {
		++nodes[nextid].color;
		return;
	}
	dfs(nextid);
}
int tag_a_circle(int nid)
{
	int ncnodes = 0;
	int i;
	assert(nodes[nid].color > 1);
	nodes[nid].color = -1;
	++ncnodes;
	for (i = nodes[nid].nextid; nodes[i].color >= 0; i = nodes[i].nextid) {
		nodes[i].color = -1;
		++ncnodes;
	}
	return ncnodes;
}
long long pow2mod(const int n)
{
	long long power = 1;
	int i;
	for (i = 0; i < n; ++i)
		power = (power * 2) % MAGIC;
	assert(power);
	return power;
}
long long compute(void)
{
	int i, nouters, ninners;
	long long result = 1, nways;
	nouters = nnodes;
	for_each_node(i) {
		if (nodes[i].color > 1) {
			ninners = tag_a_circle(i);
			nouters -= ninners;
			nways = pow2mod(ninners) - 2;
			correct(&nways);
			result = (result * nways) % MAGIC;
		}
	}
	result = (pow2mod(nouters) * result) % MAGIC;
	return result;
}
int main(void)
{
	int i;
	setbuf(stdout, NULL);
	scanf("%d", &nnodes);
	for_each_node(i) {
		scanf("%d", &nodes[i].nextid);
		nodes[i].color = 0;
		nodes[i].nid = i;
	}
	for_each_node(i) {
		if (nodes[i].color == 0)
			dfs(i);
	}
	printf("%lld\n", compute());
	return 0;
}


#include<stdio.h>

#define MOD 1000000007

int n;
int map[200001];
int deep[200001];
int dfs_loop_number[200001];

int loop_amount;
int loop_size[200000];
int loop_size_amount;

void dfs(int current_location, int current_deep, int loop_number) {
    deep[current_location] = current_deep;
    dfs_loop_number[current_location] = loop_number;
    if (deep[map[current_location]] == 0) {
        dfs(map[current_location], current_deep + 1, loop_number);
    } else if (loop_number == dfs_loop_number[map[current_location]]) {
        loop_size[loop_amount++] = current_deep - deep[map[current_location]] + 1;
        loop_size_amount += current_deep - deep[map[current_location]] + 1;
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", map + i);
    }
    int loop_number = 1;
    for (int i = 1; i <= n; i++) {
        if (deep[i] == 0) {
            dfs(i, 1, loop_number++);
        }
    }
    long long answer = 1;

//    for (int i = 0; i < loop_amount; i++) {
//        long long quotient = loop_size[i] / 30;
//        long long remain = loop_size[i] % 30;
//        for (int j = 0; j < quotient; j++) {
//            answer <<= 30;
//            if (answer >= MOD + 2) {
//                answer %= MOD;
//            }
//        }
//        answer <<= remain;
//        answer -= 2;
//        if (answer >= MOD) {
//            answer %= MOD;
//        }
//    }
//    long long quotient = (n - loop_size_amount) / 30;
//    long long remain = (n - loop_size_amount) % 30;
//    for (int i = 0; i < quotient; i++) {
//        answer <<= 30;
//        if (answer >= MOD) {
//            answer %= MOD;
//        }
//    }
//    answer <<= remain;
//    if (answer >= MOD) {
//        answer %= MOD;
//    }

    for (int i = 0; i < loop_amount; i++) {
        for (int j = 0; j < loop_size[i]; j++) {
            answer *= 2;
            if (answer >= MOD + 2) {
                answer %= MOD;
            }
        }
        answer -= 2;
    }
    for (int i = 0; i < n - loop_size_amount; i++) {
        answer *= 2;
        if (answer >= MOD) {
            answer %= MOD;
        }
    }

    printf("%lld", answer);
}


#include<stdio.h>

#define MOD 1000000007

int n;
int map[200001];
int deep[200001];
int dfs_loop_number[200001];

int loop_amount;
int loop_size[200000];
int loop_size_amount;

void dfs(int current_location, int current_deep, int loop_number) {
    deep[current_location] = current_deep;
    dfs_loop_number[current_location] = loop_number;
    if (deep[map[current_location]] == 0) {
        dfs(map[current_location], current_deep + 1, loop_number);
    } else if (loop_number == dfs_loop_number[map[current_location]]) {
        loop_size[loop_amount++] = current_deep - deep[map[current_location]] + 1;
        loop_size_amount += current_deep - deep[map[current_location]] + 1;
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", map + i);
    }
    int loop_number = 1;
    for (int i = 1; i <= n; i++) {
        if (deep[i] == 0) {
            dfs(i, 1, loop_number++);
        }
    }
    long long answer = 1;
    for (int i = 0; i < loop_amount; i++) {
        long long quotient = loop_size[i] / 30;
        long long remain = loop_size[i] % 30;
        for (int j = 0; j < quotient; j++) {
            answer <<= 30;
            if (answer >= MOD + 2) {
                answer %= MOD;
            }
        }
        answer <<= remain;
        answer -= 2;
        if (answer >= MOD) {
            answer %= MOD;
        }
    }
    long long quotient = (n - loop_size_amount) / 30;
    long long remain = (n - loop_size_amount) % 30;
    for (int i = 0; i < quotient; i++) {
        answer <<= 30;
        if (answer >= MOD) {
            answer %= MOD;
        }
    }
    answer <<= remain;
    if (answer >= MOD) {
        answer %= MOD;
    }
    printf("%lld", answer);
}


#include<stdio.h>

#define MOD 1000000007

int n;
int map[200001];
int deep[200001];
int dfs_loop_number[200001];

int loop_amount;
int loop_size[200000];
int loop_size_amount;

void dfs(int current_location, int current_deep, int loop_number) {
    deep[current_location] = current_deep;
    dfs_loop_number[current_location] = loop_number;
    if (deep[map[current_location]] == 0) {
        dfs(map[current_location], current_deep + 1, loop_number);
    } else if (loop_number == dfs_loop_number[map[current_location]]) {
        loop_size[loop_amount++] = current_deep - deep[map[current_location]] + 1;
        loop_size_amount += current_deep - deep[map[current_location]] + 1;
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", map + i);
    }
    int loop_number = 1;
    for (int i = 1; i <= n; i++) {
        if (deep[i] == 0) {
            dfs(i, 1, loop_number++);
        }
    }
    long long answer = 1;
    long long answer_loop = 1;

    for (int i = 0; i < loop_amount; i++) {
        answer_loop = 1;
        long long quotient = loop_size[i] / 30;
        long long remain = loop_size[i] % 30;
        for (int j = 0; j < quotient; j++) {
            answer_loop <<= 30;
            if (answer_loop >= MOD + 2) {
                answer_loop %= MOD;
            }
        }
        answer_loop <<= remain;
        answer_loop -= 2;
        if (answer_loop >= MOD) {
            answer_loop %= MOD;
        }
        answer *= answer_loop;
        if (answer >= MOD) {
            answer %= MOD;
        }
    }
    long long quotient = (n - loop_size_amount) / 30;
    long long remain = (n - loop_size_amount) % 30;
    for (int i = 0; i < quotient; i++) {
        answer <<= 30;
        if (answer >= MOD) {
            answer %= MOD;
        }
    }
    answer <<= remain;
    if (answer >= MOD) {
        answer %= MOD;
    }

//    for (int i = 0; i < loop_amount; i++) {
//        for (int j = 0; j < loop_size[i]; j++) {
//            answer *= 2;
//            if (answer >= MOD + 2) {
//                answer %= MOD;
//            }
//        }
//        answer -= 2;
//    }
//    for (int i = 0; i < n - loop_size_amount; i++) {
//        answer *= 2;
//        if (answer >= MOD) {
//            answer %= MOD;
//        }
//    }

    printf("%lld", answer);
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.util.HashMap;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author FinnTheHuman
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public final long mod = 1000000007;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int[] v = new int[n + 1];
            long[] pow2mod = new long[n + 1];
            pow2mod[0] = 1;
            for (int i = 1; i <= n; ++i) pow2mod[i] = (2L * pow2mod[i - 1]) % mod;
            for (int i = 0; i < n; ++i) v[i] = in.nextInt() - 1;
            boolean[] vis = new boolean[n];
            ArrayList<Integer> cycles = new ArrayList<>();
            int independent = n;
            for (int i = 0; i < n; ++i) {
                if (!vis[i]) {
                    HashMap<Integer, Integer> order = new HashMap<>();
                    order.put(i, 0);
                    vis[i] = true;
                    int cur = v[i];
                    while (!vis[cur]) {
                        order.put(cur, order.size());
                        vis[cur] = true;
                        cur = v[cur];
                    }
                    if (order.containsKey(cur)) {
                        cycles.add(order.size() - order.get(cur));
                    }
                }
            }
            long ans = 1L;
            for (int i = 0; i < cycles.size(); ++i) {
                ans *= (pow2mod[cycles.get(i)] - 2) % mod;
                ans %= mod;
                independent -= cycles.get(i);
            }
            ans = (ans * pow2mod[independent]) % mod;
            out.println(ans);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 65536 / 2);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.util.HashMap;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author FinnTheHuman
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public final long mod = 1000000007;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int[] v = new int[n + 1];
            long[] pow2mod = new long[n + 1];
            pow2mod[0] = 1;
            for (int i = 1; i <= n; ++i) pow2mod[i] = (2L * pow2mod[i - 1]) % mod;
            for (int i = 0; i < n; ++i) v[i] = in.nextInt() - 1;
            boolean[] vis = new boolean[n];
            ArrayList<Integer> cycles = new ArrayList<>();
            long independent = 0;
            for (int i = 0; i < n; ++i) {
                if (!vis[i]) {
                    HashMap<Integer, Integer> order = new HashMap<>();
                    order.put(i, 0);
                    vis[i] = true;
                    int cur = v[i];
                    while (!vis[cur] && !order.containsKey(cur)) {
                        order.put(cur, order.size());
                        vis[cur] = true;
                        cur = v[cur];
                    }
                    if (order.containsKey(cur)) {
                        cycles.add(order.size() - order.get(cur));
                        independent += order.size() - (cycles.get(cycles.size() - 1));
                    } else independent += order.size();
                }
            }
            long ans = 0;
            for (int i = 0; i < cycles.size(); ++i) {
                ans += (pow2mod[(int) independent] * (pow2mod[(Integer) cycles.get(i)] - 2)) % mod;
                ans %= mod;
            }
            out.println(ans);
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 65536 / 2);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;

public class DirectedRoads {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();

		adjList = new ArrayList[N];
		visited = new boolean[N];
		dfs_num = new int[N]; dfs_low = new int[N];
		s = new Stack<Integer>();

		Arrays.fill(dfs_num, -1);

		for(int i=0; i<N; i++)
			adjList[i] = new ArrayList<Integer>();

		for(int i=0; i<N; i++)
		{
			adjList[i].add(sc.nextInt()-1);
		}

		sizes = new ArrayList<Integer>();

		for(int i=0; i<N; i++)
			if(dfs_num[i] == -1)
				tarjanSCC(i);

		long res = 1;
		int total = 0;
		for(int size : sizes)
		{
			total += size;
			int tr = 1;
			for(int i=0; i<size; i++)
				tr = (tr * 2) % MOD;
			tr -= 2;
			res *= tr;
		}

		for(int i=0; i<N - total; i++)
			res = (res * 2) % MOD;

		System.out.println(res);
	}

	static int MOD = (int) 1e9 + 7;
	static ArrayList<Integer> adjList[];
	static boolean visited[];
	static int [] dfs_num, dfs_low;
	static int dfs_counter, num_SCC, N;
	static Stack<Integer> s;

	static ArrayList<Integer> sizes;

	static void tarjanSCC(int u)
	{
		dfs_num[u] = dfs_low[u] = dfs_counter++;
		visited[u] = true;
		s.push(u);

		for(int v : adjList[u])
		{
			if(dfs_num[v] == -1){
				tarjanSCC(v);
			}
			if(visited[v])
				dfs_low[u] = Math.min(dfs_low[u], dfs_low[v]);

		}

		if(dfs_low[u] == dfs_num[u])
		{
			// u is a root of a SCC
			num_SCC++;
			int sccS = 0;
			while(true)
			{
				sccS++;
				int v = s.pop();
				visited[v] = false;
				if(v == u)
					break;

			}
			if(sccS > 1)
				sizes.add(sccS);
		}
	}
}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;

public class DirectedRoads {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();

		adjList = new ArrayList[N];
		visited = new boolean[N];
		dfs_num = new int[N]; dfs_low = new int[N];
		s = new Stack<Integer>();

		Arrays.fill(dfs_num, -1);

		for(int i=0; i<N; i++)
			adjList[i] = new ArrayList<Integer>();

		for(int i=0; i<N; i++)
		{
			adjList[i].add(sc.nextInt()-1);
		}

		for(int i=0; i<N; i++)
			if(dfs_num[i] == -1)
				tarjanSCC(i);

		if(size == 1)
			size = 0;

		long res = 1;
		for(int i=0; i<size; i++)
			res = (res * 2) % MOD;

		res -= 2;

		for(int i=0; i<N - size; i++)
			res = (res * 2) % MOD;

		System.out.println(res);
	}

	static int MOD = (int) 1e9 + 7;
	static ArrayList<Integer> adjList[];
	static boolean visited[];
	static int [] dfs_num, dfs_low;
	static int dfs_counter, num_SCC, N;
	static Stack<Integer> s;

	static int size;

	static void tarjanSCC(int u)
	{
		dfs_num[u] = dfs_low[u] = dfs_counter++;
		visited[u] = true;
		s.push(u);

		for(int v : adjList[u])
		{
			if(dfs_num[v] == -1){
				tarjanSCC(v);
			}
			if(visited[v])
				dfs_low[u] = Math.min(dfs_low[u], dfs_low[v]);

		}

		if(dfs_low[u] == dfs_num[u])
		{
			// u is a root of a SCC
			num_SCC++;
			int sccS = 0;
			while(true)
			{
				sccS++;
				int v = s.pop();
				visited[v] = false;
				if(v == u)
					break;

			}

			size = Math.max(size, sccS);
		}
	}
}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;

public class DirectedRoads {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		N = sc.nextInt();

		adjList = new ArrayList[N];
		visited = new boolean[N];
		dfs_num = new int[N]; dfs_low = new int[N];
		s = new Stack<Integer>();

		Arrays.fill(dfs_num, -1);

		for(int i=0; i<N; i++)
			adjList[i] = new ArrayList<Integer>();

		for(int i=0; i<N; i++)
		{
			adjList[i].add(sc.nextInt()-1);
		}

		sizes = new ArrayList<Integer>();

		for(int i=0; i<N; i++)
			if(dfs_num[i] == -1)
				tarjanSCC(i);

		long res = 1;
		int total = 0;
		for(int size : sizes)
		{
			total += size;
			int tr = 1;
			for(int i=0; i<size; i++)
				tr = (tr * 2) % MOD;
			tr -= 2;
			res = (res * tr) % MOD;
		}

		for(int i=0; i<N - total; i++)
			res = (res * 2) % MOD;

		System.out.println(res);
	}

	static int MOD = (int) 1e9 + 7;
	static ArrayList<Integer> adjList[];
	static boolean visited[];
	static int [] dfs_num, dfs_low;
	static int dfs_counter, num_SCC, N;
	static Stack<Integer> s;

	static ArrayList<Integer> sizes;

	static void tarjanSCC(int u)
	{
		dfs_num[u] = dfs_low[u] = dfs_counter++;
		visited[u] = true;
		s.push(u);

		for(int v : adjList[u])
		{
			if(dfs_num[v] == -1){
				tarjanSCC(v);
			}
			if(visited[v])
				dfs_low[u] = Math.min(dfs_low[u], dfs_low[v]);

		}

		if(dfs_low[u] == dfs_num[u])
		{
			// u is a root of a SCC
			num_SCC++;
			int sccS = 0;
			while(true)
			{
				sccS++;
				int v = s.pop();
				visited[v] = false;
				if(v == u)
					break;

			}
			if(sccS > 1)
				sizes.add(sccS);
		}
	}
}


import java.io.*;
import java.util.*;
public class test
{
    static long count=0,ans=1, M=1000000007;
    static int vertex[];
    static int visited[];
    static int parent[];

    public static void main(String args[])
    {
        //System.out.println("Welcome");
        inputs in=new inputs(System.in);
        int n=in.nextInt();
        vertex=new int[n+1];
         visited=new int[n+1];
        parent=new int[n+1];

        for(int i=1;i<=n;i++)
        {
            vertex[i]=in.nextInt();
        }

        for(int i=1;i<=n;i++)
        {
            if(visited[i]>0) continue;
            else
             dfs(i,i);
        }

        if(count<n)
        {
            ans=ans*((long)Math.pow(2,n-count)%M);
            ans=ans%M;
        }

        out(""+ans);
    }

    static void dfs(int i,int z)
    {
        visited[i]=z;
        int j=vertex[i];
        if(visited[j]==z)
        {
            int a=i;int tcount=1;
            while(a!=j)
            {
                tcount++;
                a=parent[a];
            }
            count+=tcount;
            ans=ans*((long)Math.pow(2,tcount)%M-2);
            ans=ans%M;
        }
        else if(visited[j]>0) return;
        else
        {
            parent[j]=i;
            dfs(j,z);
        }
    }

    static void out(String s)
    {
        System.out.println(s);
    }
}

class inputs
{
    public BufferedReader reader;
    public StringTokenizer token;

    inputs(InputStream str)
    {
        reader=new BufferedReader(new InputStreamReader(str));
        token=null;
    }

    int nextInt()
    {
        while(token==null||!token.hasMoreTokens())
        {
            try { token=new StringTokenizer(reader.readLine());   }
            catch(IOException e){  throw new RuntimeException(e); }
        }
        return Integer.parseInt(token.nextToken());
    }

    String next()
    {
        while(token==null||!token.hasMoreTokens())
        {
            try { token=new StringTokenizer(reader.readLine());   }
            catch(IOException e){  throw new RuntimeException(e); }
        }
        return token.nextToken();
    }

}


import java.io.*;
import java.util.*;
public class test
{
    static long count=0,ans=1, M=1000000007;
    static int vertex[];
    static int visited[];
    static int parent[];

    public static void main(String args[])
    {
        //System.out.println("Welcome");
        inputs in=new inputs(System.in);
        long n=in.nextInt();
        vertex=new int[(int)n+1];
         visited=new int[(int)n+1];
        parent=new int[(int)n+1];

        for(int i=1;i<=n;i++)
        {
            vertex[i]=in.nextInt();
        }

        for(int i=1;i<=n;i++)
        {
            if(visited[i]>0) continue;
            else
             dfs(i,i);
        }

        if(count<n)
        {
            ans=ans*((long)BigPow(2,n-count,M)%M);
            ans=ans%M;
        }

        out(""+ans);
    }

    static void dfs(int i,int z)
    {
        visited[i]=z;
        int j=vertex[i];
        if(visited[j]==z)
        {
            int a=i;int tcount=1;
            while(a!=j)
            {
                tcount++;
                a=parent[a];
            }
            count+=tcount;
            ans=ans%M;
            ans=ans*((long)BigPow(2,tcount,M)%M-2L);
            ans=ans%M;
        }
        else if(visited[j]>0) return;
        else
        {
            parent[j]=i;
            dfs(j,z);
        }
    }

    static void out(String s)
    {
        System.out.println(s);
    }

    static int BigPow(int a,long b,long M)
    {
        long ans=1,A=a;

        while(b!=1)
        {
            if(b%2!=0) { ans=ans*A; ans=ans%M; }
            A=(A*A)%M;
            b=b/2;
        }

        ans=(ans*A)%M;
        return (int)ans;
    }
}

class inputs
{
    public BufferedReader reader;
    public StringTokenizer token;

    inputs(InputStream str)
    {
        reader=new BufferedReader(new InputStreamReader(str));
        token=null;
    }

    int nextInt()
    {
        while(token==null||!token.hasMoreTokens())
        {
            try { token=new StringTokenizer(reader.readLine());   }
            catch(IOException e){  throw new RuntimeException(e); }
        }
        return Integer.parseInt(token.nextToken());
    }

    String next()
    {
        while(token==null||!token.hasMoreTokens())
        {
            try { token=new StringTokenizer(reader.readLine());   }
            catch(IOException e){  throw new RuntimeException(e); }
        }
        return token.nextToken();
    }

}


import java.io.*;
import java.util.*;
public class test
{
    static long count=0,ans=1, M=1000000007;
    static int vertex[];
    static int visited[];
    static int parent[];

    public static void main(String args[])
    {
        //System.out.println("Welcome");
        inputs in=new inputs(System.in);
        long n=in.nextInt();
        vertex=new int[(int)n+1];
         visited=new int[(int)n+1];
        parent=new int[(int)n+1];

        for(int i=1;i<=n;i++)
        {
            vertex[i]=in.nextInt();
        }

        for(int i=1;i<=n;i++)
        {
            if(visited[i]>0) continue;
            else
             dfs(i,i);
        }

        if(count<n)
        {
            ans=ans*((long)Math.pow(2L,n-count)%M);
            ans=ans%M;
        }

        out(""+ans);
    }

    static void dfs(int i,int z)
    {
        visited[i]=z;
        int j=vertex[i];
        if(visited[j]==z)
        {
            int a=i;int tcount=1;
            while(a!=j)
            {
                tcount++;
                a=parent[a];
            }
            count+=tcount;
            ans=ans%M;
            ans=ans*((long)Math.pow(2,tcount)%M-2L);
            ans=ans%M;
        }
        else if(visited[j]>0) return;
        else
        {
            parent[j]=i;
            dfs(j,z);
        }
    }

    static void out(String s)
    {
        System.out.println(s);
    }
}

class inputs
{
    public BufferedReader reader;
    public StringTokenizer token;

    inputs(InputStream str)
    {
        reader=new BufferedReader(new InputStreamReader(str));
        token=null;
    }

    int nextInt()
    {
        while(token==null||!token.hasMoreTokens())
        {
            try { token=new StringTokenizer(reader.readLine());   }
            catch(IOException e){  throw new RuntimeException(e); }
        }
        return Integer.parseInt(token.nextToken());
    }

    String next()
    {
        while(token==null||!token.hasMoreTokens())
        {
            try { token=new StringTokenizer(reader.readLine());   }
            catch(IOException e){  throw new RuntimeException(e); }
        }
        return token.nextToken();
    }

}


import java.util.Scanner;
import java.util.Map;
import java.util.HashMap;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;

public class DirectedRoads
{
	public static void main(String[] args) throws IOException
	{
		BufferedInputStream in = new BufferedInputStream(System.in);
		int n = nextInt(in);
		int[] roads = new int[n + 1];
		for (int i = 1; i <= n; i++)
		{
			roads[i] = nextInt(in);
		}
		int nextStart = 2, current = 1, count = 1;
		boolean[] visitedAtAll = new boolean[n + 1];
		Map<Integer, Integer> visitedNow = new HashMap<>();
		long tally = 1;
		while (current <= n)
		{
			visitedAtAll[current] = true;
			visitedNow.put(current, count);
			int next = roads[current];
			if (visitedAtAll[next])
			{
				long add = 1;
				if (visitedNow.containsKey(next))
				{
					int cyc = count - visitedNow.get(next) + 1;
					add = modPow(2, cyc, 1000000000 + 7);
					// for (int i = 0; i < cyc; i++)
					// {
						// add *= 2;
						// add %= 1000000000 + 7;
					// }
					add -= 2;
					if (add < 0)
					{
						add = add + 1000000000 + 7;
					}
					tally *= add;
					tally %= 1000000000 + 7;
					count -= cyc;
				}
				add = modPow(2, count, 1000000000 + 7);
				// for (int i = 0; i < count; i++)
				// {
					// add *= 2;
					// add %= 1000000000 + 7;
				// }
				tally *= add;
				tally %= 1000000000 + 7;
				while (nextStart <= n && visitedAtAll[nextStart])
				{
					nextStart++;
				}
				count = 1;
				visitedNow = new HashMap<Integer, Integer>();
				current = nextStart;
				nextStart++;
			}
			else
			{
				count++;
				current = next;
			}
		}
		System.out.println(tally);
	}

	public static int nextInt(BufferedInputStream in) throws IOException
	{
		int next = 0;
		boolean haveNext = false;
		int b;
		while ((b = in.read()) != -1)
		{
			if ('0' <= b && b <= '9')
			{
				next = 10*next + (b - '0');
				haveNext = true;
			}
			else if (haveNext)
			{
				break;
			}
		}
		return next;
	}

	public static long modPow(long base, long exp, long mod)
	{
		long[] a = new long[30]; // Compute from args later? log_2(exp) <= length
		a[0] = base;
		for (int i = 1; i < a.length; i++)
		{
			a[i] = a[i-1]*a[i-1];
			a[i] %= mod;
		}
		long res = 1;
		int i = 0;
		while (exp > 0)
		{
			if (exp % 2 == 1)
			{
				res *= a[i];
			}
			i++;
			res %= mod;
			exp /= 2;
		}
		return res;
	}
}


import java.util.Scanner;

public class DirectedRoads
{
	public static void main(String[] args)
	{
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] roads = new int[n + 1];
		for (int i = 1; i <= n; i++)
		{
			roads[i] = in.nextInt();
		}
		int nextStart = 2, current = 1, count = 1;
		boolean[] visitedAtAll = new boolean[n + 1];
		int[] visitedNow = new int[n + 1];
		long tally = 1;
		while (current <= n)
		{
			visitedAtAll[current] = true;
			visitedNow[current] = count;
			int next = roads[current];
			if (visitedAtAll[next])
			{
				long add = 1;
				if (visitedNow[next] > 0)
				{
					int cyc = count - visitedNow[next] + 1;
					add = (long)Math.pow(2, cyc);
					// for (int i = 0; i < cyc; i++)
					// {
						// add *= 2;
						// add %= 1000000000 + 7;
					// }
					add -= 2;
					tally *= add;
					tally %= 1000000000 + 7;
					count -= cyc;
				}
				add = (long)Math.pow(2, count);
				// for (int i = 0; i < count; i++)
				// {
					// add *= 2;
					// add %= 1000000000 + 7;
				// }
				tally *= add;
				tally %= 1000000000 + 7;
				while (nextStart <= n && visitedAtAll[nextStart])
				{
					nextStart++;
				}
				count = 1;
				visitedNow = new int[n + 1];
				current = nextStart;
				nextStart++;
			}
			else
			{
				count++;
				current = next;
			}
		}
		System.out.println(tally);
	}
}


import java.util.Scanner;
import java.util.Map;
import java.util.HashMap;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;

public class DirectedRoads
{
	public static void main(String[] args) throws IOException
	{
		BufferedInputStream in = new BufferedInputStream(System.in);
		int n = nextInt(in);
		int[] roads = new int[n + 1];
		for (int i = 1; i <= n; i++)
		{
			roads[i] = nextInt(in);
		}
		int nextStart = 2, current = 1, count = 1;
		boolean[] visitedAtAll = new boolean[n + 1];
		Map<Integer, Integer> visitedNow = new HashMap<>();
		long tally = 1;
		while (current <= n)
		{
			visitedAtAll[current] = true;
			visitedNow.put(current, count);
			int next = roads[current];
			if (visitedAtAll[next])
			{
				long add = 1;
				if (visitedNow.containsKey(next))
				{
					int cyc = count - visitedNow.get(next) + 1;
					add = (long)Math.pow(2, cyc);
					// for (int i = 0; i < cyc; i++)
					// {
						// add *= 2;
						// add %= 1000000000 + 7;
					// }
					add -= 2;
					tally *= add;
					tally %= 1000000000 + 7;
					count -= cyc;
				}
				add = (long)Math.pow(2, count);
				// for (int i = 0; i < count; i++)
				// {
					// add *= 2;
					// add %= 1000000000 + 7;
				// }
				tally *= add;
				tally %= 1000000000 + 7;
				while (nextStart <= n && visitedAtAll[nextStart])
				{
					nextStart++;
				}
				count = 1;
				for (int i = 0; )
				visitedNow = new HashMap<Integer, Integer>();
				current = nextStart;
				nextStart++;
			}
			else
			{
				count++;
				current = next;
			}
		}
		System.out.println(tally);
	}

	public static int nextInt(BufferedInputStream in) throws IOException
	{
		int next = 0;
		boolean haveNext = false;
		int b;
		while ((b = in.read()) != -1)
		{
			if ('0' <= b && b <= '9')
			{
				next = 10*next + (b - '0');
				haveNext = true;
			}
			else if (haveNext)
			{
				break;
			}
		}
		return next;
	}
}


import java.util.Scanner;
import java.util.Map;
import java.util.HashMap;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;

public class DirectedRoads
{
	public static void main(String[] args) throws IOException
	{
		BufferedInputStream in = new BufferedInputStream(System.in);
		int n = nextInt(in);
		int[] roads = new int[n + 1];
		for (int i = 1; i <= n; i++)
		{
			roads[i] = nextInt(in);
		}
		int nextStart = 2, current = 1, count = 1;
		boolean[] visitedAtAll = new boolean[n + 1];
		Map<Integer, Integer> visitedNow = new HashMap<>();
		long tally = 1;
		while (current <= n)
		{
			visitedAtAll[current] = true;
			visitedNow.put(current, count);
			int next = roads[current];
			if (visitedAtAll[next])
			{
				long add = 1;
				if (visitedNow.containsKey(next))
				{
					int cyc = count - visitedNow.get(next) + 1;
					add = (long)Math.pow(2, cyc);
					// for (int i = 0; i < cyc; i++)
					// {
						// add *= 2;
						// add %= 1000000000 + 7;
					// }
					add -= 2;
					tally *= add;
					tally %= 1000000000 + 7;
					count -= cyc;
				}
				add = (long)Math.pow(2, count);
				// for (int i = 0; i < count; i++)
				// {
					// add *= 2;
					// add %= 1000000000 + 7;
				// }
				tally *= add;
				tally %= 1000000000 + 7;
				while (nextStart <= n && visitedAtAll[nextStart])
				{
					nextStart++;
				}
				count = 1;
				visitedNow = new HashMap<Integer, Integer>();
				current = nextStart;
				nextStart++;
			}
			else
			{
				count++;
				current = next;
			}
		}
		System.out.println(tally);
	}

	public static int nextInt(BufferedInputStream in) throws IOException
	{
		int next = 0;
		boolean haveNext = false;
		int b;
		while ((b = in.read()) != -1)
		{
			if ('0' <= b && b <= '9')
			{
				next = 10*next + (b - '0');
				haveNext = true;
			}
			else if (haveNext)
			{
				break;
			}
		}
		return next;
	}
}


import java.util.Scanner;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;

public class DirectedRoads
{
	public static void main(String[] args) throws IOException
	{
		BufferedInputStream in = new BufferedInputStream(System.in);
		int n = nextInt(in);
		int[] roads = new int[n + 1];
		for (int i = 1; i <= n; i++)
		{
			roads[i] = nextInt(in);
		}
		int nextStart = 2, current = 1, count = 1;
		boolean[] visitedAtAll = new boolean[n + 1];
		int[] visitedNow = new int[n + 1];
		long tally = 1;
		while (current <= n)
		{
			visitedAtAll[current] = true;
			visitedNow[current] = count;
			int next = roads[current];
			if (visitedAtAll[next])
			{
				long add = 1;
				if (visitedNow[next] > 0)
				{
					int cyc = count - visitedNow[next] + 1;
					add = (long)Math.pow(2, cyc);
					// for (int i = 0; i < cyc; i++)
					// {
						// add *= 2;
						// add %= 1000000000 + 7;
					// }
					add -= 2;
					tally *= add;
					tally %= 1000000000 + 7;
					count -= cyc;
				}
				add = (long)Math.pow(2, count);
				// for (int i = 0; i < count; i++)
				// {
					// add *= 2;
					// add %= 1000000000 + 7;
				// }
				tally *= add;
				tally %= 1000000000 + 7;
				while (nextStart <= n && visitedAtAll[nextStart])
				{
					nextStart++;
				}
				count = 1;
				visitedNow = new int[n + 1];
				current = nextStart;
				nextStart++;
			}
			else
			{
				count++;
				current = next;
			}
		}
		System.out.println(tally);
	}

	public static int nextInt(BufferedInputStream in) throws IOException
	{
		int next = 0;
		boolean haveNext = false;
		int b;
		while ((b = in.read()) != -1)
		{
			if ('0' <= b && b <= '9')
			{
				next = 10*next + (b - '0');
				haveNext = true;
			}
			else if (haveNext)
			{
				break;
			}
		}
		return next;
	}
}


import java.util.Scanner;

public class DirectedRoads
{
	public static void main(String[] args)
	{
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int[] roads = new int[n + 1];
		for (int i = 1; i <= n; i++)
		{
			roads[i] = in.nextInt();
		}
		int nextStart = 2, current = 1, count = 1;
		boolean[] visitedAtAll = new boolean[n + 1];
		int[] visitedNow = new int[n + 1];
		long tally = 1;
		while (current <= n)
		{
			visitedAtAll[current] = true;
			visitedNow[current] = count;
			int next = roads[current];
			if (visitedAtAll[next])
			{
				long add = 1;
				if (visitedNow[next] > 0)
				{
					int cyc = count - visitedNow[next] + 1;
					for (int i = 0; i < cyc; i++)
					{
						add *= 2;
						add %= 1000000000 + 7;
					}
					add -= 2;
					tally *= add;
					tally %= 1000000000 + 7;
					count -= cyc;
				}
				add = 1;
				for (int i = 0; i < count; i++)
				{
					add *= 2;
					add %= 1000000000 + 7;
				}
				tally *= add;
				tally %= 1000000000 + 7;
				while (nextStart <= n && visitedAtAll[nextStart])
				{
					nextStart++;
				}
				count = 1;
				visitedNow = new int[n + 1];
				current = nextStart;
				nextStart++;
			}
			else
			{
				count++;
				current = next;
			}
		}
		System.out.println(tally);
	}
}


import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class D {
	private static final int MOD = 1000_000_007;

	private static void dfs1(int v, List<List<Integer>> graph, boolean[] used, List<Integer> order) {
		used[v] = true;
		for (int a : graph.get(v)) {
			if (!used[a]) {
				dfs1(a, graph, used, order);
			}
		}
		order.add(v);
	}

	private static void dfs2(int v, List<List<Integer>> graph, boolean[] used, List<Integer> component) {
		used[v] = true;
		component.add(v);
		for (int a : graph.get(v)) {
			if (!used[a]) {
				dfs2(a, graph, used, component);
			}
		}
	}

	public static void main(String[] args) throws IOException {
		try (FastScanner s = new FastScanner()) {
			final int n = s.nextInt();
			final int[] a = new int[n];
			for (int i = 0; i < n; ++i) {
				a[i] = s.nextInt() - 1;
			}
			final List<List<Integer>> graph = new ArrayList<>();
			for (int i = 0; i < n; ++i) {
				graph.add(new ArrayList<Integer>());
			}
			for (int i = 0; i < n; ++i) {
				graph.get(i).add(a[i]);
			}
			final List<List<Integer>> rgraph = new ArrayList<>();
			for (int i = 0; i < n; ++i) {
				rgraph.add(new ArrayList<Integer>());
			}
			for (int i = 0; i < n; ++i) {
				rgraph.get(a[i]).add(i);
			}
			final List<Integer> order = new ArrayList<>();
			final boolean[] used = new boolean[n];
			for (int i = 0; i < n; ++i) {
				if (!used[i]) {
					dfs1(i, graph, used, order);
				}
			}

			final long[] powers = new long[n + 1];
			powers[0] = 1;
			for (int i = 1; i <= n; ++i) {
				powers[i] = (2*powers[i - 1]) % MOD;
			}

			long res = 1;

			Arrays.fill(used, false);
			for (int i = 0; i < n; ++i) {
				int v = order.get(n - i - 1);
				if (!used[v]) {
					final List<Integer> component = new ArrayList<>();
					dfs2(v, rgraph, used, component);
					if (component.size() > 1) {
						res = ((res * (powers[component.size()] - 2))) % MOD;
					} else {
						res = (2*res) % MOD;
					}
				}
			}
			System.out.println(res);
		}
	}

	private static class FastScanner implements Closeable {
		private final BufferedReader reader;
		private String[] tokens;
		private int next;

		FastScanner() {
			reader = new BufferedReader(new InputStreamReader(System.in));
		}

		String next() throws IOException {
			if (tokens == null || next == tokens.length) {
				tokens = reader.readLine().split(" ");
				next = 0;
			}
			return tokens[next++];
		}

		int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		@Override
		public void close() throws IOException {
			reader.close();
		}
	}
}


import java.util.*;
import java.io.*;

public class Practice {
int s[];
int a[];
int l[];
	int c=0;
	 int n;
	 void solve()
	 {
		 int mod =(int)1e9 + 7;
	        n=in.nextInt();

	         a=new int[n];
	        for(int i=0;i<n;i++)
	        	a[i]=in.nextInt()-1;
	        s=new int[n];
	        l=new int[n];
	        for(int i=0;i<n;i++)
	        {
	        	if(s[i]==0)
	        		dfs(i);
	        }
	        long[] p2 = new long[(int)2e5+5];
	        p2[0] = 1;
	        for (int i = 1; i < (int)2e5+5; i++) p2[i] = 2 * p2[i - 1] % mod;

	        long ans = 1;
	        for (int i = 0; i < c; i++) {
	            n -= l[i];
	            ans = ans * ((p2[l[i]] - 2 + mod) % mod) % mod;
	        }
	        ans = ans * p2[n] % mod;

	        w.println(ans);
	 }
void dfs(int i)
{
	  s[i]=1;
	  if(s[a[i]]==0)
		  dfs(a[i]);
	  else if(s[a[i]]==1)
	  {
		  cycle(i);
	  }
	  s[i]=2;

}
void cycle(int i)
{
	for(int j=a[i];j!=i;j=a[j])
	{
		l[c]++;
	}
	l[c++]++;
}
	public static void main(String[] args){
		// TODO Auto-generated method stub

		 in = new InputReader(System.in);
	         w = new PrintWriter(System.out);

	        new Practice().solve();
	        w.close();

	       		}

	static InputReader in;
	static PrintWriter w;

 	static class  InputReader {

       private final InputStream stream;
        private final byte[] buf = new byte[8192];
        private int curChar, snumChars;
        private SpaceCharFilter filter;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        public int snext() {
            if (snumChars == -1)
                throw new InputMismatchException();
            if (curChar >= snumChars) {
                curChar = 0;
                try {
                    snumChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (snumChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = snext();
            while (isSpaceChar(c)) {
                c = snext();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = snext();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = snext();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public long nextLong() {
            int c = snext();
            while (isSpaceChar(c)) {
                c = snext();
            }
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = snext();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = snext();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public int[] nextIntArray(int n) {
            int a[] = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = nextInt();
            }
            return a;
        }

        public String readString() {
            int c = snext();
            while (isSpaceChar(c)) {
                c = snext();
            }
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = snext();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public String nextLine() {
            int c = snext();
            while (isSpaceChar(c))
                c = snext();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = snext();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        public boolean isSpaceChar(int c) {
            if (filter != null)
                return filter.isSpaceChar(c);
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public interface SpaceCharFilter {
            public boolean isSpaceChar(int ch);
        }
        public long gcd(long a, long b) {
    		return b == 0 ? a : gcd(b, a % b);
    	}

    	public long lcm(long a, long b) {
    		return a * b / (gcd(a, b));
    	}
    }

}


import java.io.*;
import java.util.*;
/**
 *
 * @author Sourav Kumar Paul
 */
public class SolveD {
    public static ArrayList<Integer> adj[];
    public static boolean marked[];
    public static int inStack[];
    public static long ans, count, mod = 1000000007;
    public static void main(String[] args) throws IOException{
        Reader in = new Reader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
       int n = in.nextInt();
       adj = new ArrayList[n];
       for(int i=0; i<n; i++)
           adj[i] = new ArrayList<>();
       for(int i=0; i<n; i++)
       {
           adj[i].add(in.nextInt()-1);
       }
       marked = new boolean[n];
       inStack = new int[n];
       Arrays.fill(inStack,-1);
       ans = 1;
       count =0;
       for(int i=0; i<n; i++)
       {
           if(!marked[i])
           {
               dfs(i,0);
            //   out.println(i+" "+ans);
           }
       }
       long res = n-count;
       ans = (ans * modPow(2,res,mod))%mod;
       out.println(ans);
       out.flush();
       out.close();
    }
private static long modPow(long base, long exp, long mod) {

        base = base % mod;
        long result =1;
        while(exp > 0)
        {
            if(exp % 2== 1)
            {
                result = (result * base) % mod;
                exp --;
            }
            else
            {
                base = (base * base) % mod;
                exp = exp >> 1;
            }

        }
        return result;

    }
    private static void dfs(int start, int id) {

        inStack[start] = id;
        marked[start] = true;
        for(int v : adj[start])
        {
            if(marked[v] && inStack[v] != -1)
            {
                int x = inStack[start] - inStack[v]+1 ;
                count+=x;
                //System.out.println(x+" dfs");
                ans = (ans * (modPow(2,x,mod) -2 + mod)%mod)%mod;
            }
            else if(!marked[v])
            {
                dfs(v,id+1);
            }
        }
        inStack[start] = -1;
    }
    public static class Reader {
        public BufferedReader reader;
        public StringTokenizer st;

        public Reader(InputStreamReader stream) {
            reader = new BufferedReader(stream);
            st = null;
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public String nextLine() throws IOException{
            return reader.readLine();
        }
        public long nextLong(){
            return Long.parseLong(next());
        }
        public double nextDouble(){
            return Double.parseDouble(next());
        }

    }
}


import java.io.*;
import java.util.*;

public class Main {

	static InputReader in = new InputReader(System.in);
	static PrintWriter out = new PrintWriter(System.out);

	static int oo = (int)1e9;
	static int mod = 1_000_000_007;

	static int[] di = {-1, 1, 0, 0};
	static int[] dj = {0, 0, -1, 1};

	static int cnt = 0;

	public static void main(String[] args) throws IOException {

		int n = in.nextInt();
		int[] a = new int[n];
		for(int i = 0; i < n; ++i)
			a[i] = in.nextInt() - 1;
		int[] seen = new int[n];
		int[] num = new int[n];
		Arrays.fill(seen, -1);
		ArrayList<Integer> cycle = new ArrayList<>();
		for(int i = 0; i < n; ++i) {
			int j = i;
			int x = 0;
			while(seen[j] == -1) {
				seen[j] = i;
				num[j] = x++;
				j = a[j];
			}
			if(seen[j] == i) {
				cycle.add(x - num[j]);
			}
		}
		int m = n;
		long ans = 1;
		for(int c : cycle) {
			ans = ans * ((pow(2, c, mod) - 2 + mod) % mod) % mod;
			m -= c;
		}
		ans = ans * pow(2, m, mod) % mod;
		System.out.println(ans);

		out.close();
	}

	static long pow(long a, long n, long mod) {
		if(n == 0)
			return 1;
		if(n % 2 == 1)
			return a * pow(a, n-1, mod) % mod;
		long x = pow(a, n / 2, mod);
		return x * x % mod;
	}

	static class SegmentTree {
		int n;
		long[] a, seg;
		int DEFAULT_VALUE = 0;

		public SegmentTree(long[] a, int n) {
			super();
			this.a = a;
			this.n = n;
			seg = new long[n * 4 + 1];
			build(1, 0, n-1);
		}

		private long build(int node, int i, int j) {
			if(i == j)
				return seg[node] = a[i];
			long first = build(node * 2, i, (i+j) / 2);
			long second = build(node * 2 + 1, (i+j) / 2 + 1, j);
			return seg[node] = combine(first, second);
		}

		long update(int k, long value) {
			return update(1, 0, n-1, k, value);
		}

		private long update(int node, int i, int j, int k, long value) {
			if(k < i || k > j)
				return seg[node];
			if(i == j && j == k) {
				a[k] = value;
				seg[node] = value;
				return value;
			}

			int m = (i + j) / 2;
			long first = update(node * 2, i, m, k, value);
			long second = update(node * 2 + 1, m + 1, j, k, value);
			return seg[node] = combine(first, second);
		}

		long query(int l, int r) {
			return query(1, 0, n-1, l, r);
		}

		private long query(int node, int i, int j, int l, int r) {
			if(l <= i && j <= r)
				return seg[node];
			if(j < l || i > r)
				return DEFAULT_VALUE;
			int m = (i + j) / 2;
			long first = query(node * 2, i, m, l, r);
			long second = query(node * 2 + 1, m+1, j, l, r);
			return combine(first, second);
		}

		private long combine(long a, long b) {
			return a + b;
		}
	}

	static class DisjointSet {
		int n;
		int[] g;
		int[] h;
		public DisjointSet(int n) {
			super();
			this.n = n;
			g = new int[n];
			h = new int[n];
			for(int i = 0; i < n; ++i) {
				g[i] = i;
				h[i] = 1;
			}
		}
		int find(int x) {
			if(g[x] == x)
				return x;
			return g[x] = find(g[x]);
		}
		void union(int x, int y) {
			x = find(x); y = find(y);
			if(x == y)
				return;
			if(h[x] >= h[y]) {
				g[y] = x;
				if(h[x] == h[y])
					h[x]++;
			}
			else {
				g[x] = y;
			}
		}
	}

	static int[] getPi(char[] a) {
		int m = a.length;
		int j = 0;
		int[] pi = new int[m];
		for(int i = 1; i < m; ++i) {
			while(j > 0 && a[i] != a[j])
				j = pi[j-1];
			if(a[i] == a[j]) {
				pi[i] = j + 1;
				j++;
			}
		}
		return pi;
	}

	static long lcm(long a, long b) {
		return a * b / gcd(a, b);
	}

	static boolean nextPermutation(int[] a) {
		for(int i = a.length - 2; i >= 0; --i) {
			if(a[i] < a[i+1]) {
				for(int j = a.length - 1; ; --j) {
					if(a[i] < a[j]) {
						int t = a[i];
						a[i] = a[j];
						a[j] = t;
						for(i++, j = a.length - 1; i < j; ++i, --j) {
							t = a[i];
							a[i] = a[j];
							a[j] = t;
						}
						return true;
					}
				}
			}
		}
		return false;
	}

	static void shuffle(int[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			int t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static void shuffle(long[] a) {
		Random r = new Random();
		for(int i = a.length - 1; i > 0; --i) {
			int si = r.nextInt(i);
			long t = a[si];
			a[si] = a[i];
			a[i] = t;
		}
	}

	static int lower_bound(int[] a, int n, int k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}
	static int lower_bound(long[] a, int n, long k) {
		int s = 0;
		int e = n;
		int m;
		while (e - s > 0) {
			m = (s + e) / 2;
			if (a[m] < k)
				s = m + 1;
			else
				e = m;
		}
		return e;
	}

	static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b, a % b);
	}
	static long gcd(long a, long b) {
		return b == 0 ? a : gcd(b, a % b);
	}

	static class Pair implements Comparable<Pair> {
		int first, second;

		public Pair(int first, int second) {
			super();
			this.first = first;
			this.second = second;
		}

		@Override
		public int compareTo(Pair o) {
			return this.first != o.first ? this.first - o.first : this.second - o.second;
		}

//		@Override
//		public int compareTo(Pair o) {
//			return this.first != o.first ? o.first - this.first : o.second - this.second;
//		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + first;
			result = prime * result + second;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Pair other = (Pair) obj;
			if (first != other.first)
				return false;
			if (second != other.second)
				return false;
			return true;
		}
	}
}

class InputReader {

	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String readString() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isSpaceChar(c));
		return res.toString();
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Jialin Ouyang (Jialin.Ouyang@gmail.com)
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    QuickScanner in = new QuickScanner(inputStream);
    QuickWriter out = new QuickWriter(outputStream);
    TaskD solver = new TaskD();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskD {
    int n;
    OneRegularGraph graph;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      n = in.nextInt();
      graph = new OneRegularGraph(n);
      graph.init(n);
      for (int i = 0; i < n; ++i) {
        graph.add(i, in.nextInt() - 1);
      }
      graph.calc();
      int res = 1;
      for (int i = 0; i < graph.compCnt; ++i) {
        int a = graph.coreSize[i], b = graph.compSize[i] - a;
        res = IntUtils.mul(
            res,
            IntUtils.mul(
                IntUtils.sub(IntUtils.pow(2, a), 2),
                IntUtils.pow(2, b)));
      }
      out.println(res);
    }

  }

  static class OneRegularGraph extends DirectedGraph {
    public int compCnt;
    public int[] compSize;
    public int[] compIdx;
    public int[] coreSize;
    public int[] distToCore;
    public int[] closestCoreNode;
    private int[] outIdx;
    private int[] cnt;

    public OneRegularGraph(int vertexCapacity) {
      super(vertexCapacity, vertexCapacity);
      compSize = new int[vertexCapacity];
      compIdx = new int[vertexCapacity];
      coreSize = new int[vertexCapacity];
      distToCore = new int[vertexCapacity];
      closestCoreNode = new int[vertexCapacity];

      outIdx = new int[vertexCapacity];
      cnt = new int[vertexCapacity];
    }

    public void init(int vertexCnt) {
      super.init(vertexCnt);
      Arrays.fill(outIdx, 0, vertexCnt, -1);
      Arrays.fill(compIdx, 0, vertexCnt, -1);
      Arrays.fill(cnt, 0, vertexCnt, 0);
      Arrays.fill(distToCore, 0, vertexCnt, -1);
    }

    public void add(int fromIdx, int toIdx) {
      super.add(fromIdx, toIdx);
      this.outIdx[fromIdx] = toIdx;
    }

    public int calc() {
      compCnt = 0;
      for (int i = 0; i < vertexCnt; ++i) {
        if (compIdx[i] >= 0) continue;
        compSize[compCnt] = dfs(i);
        for (int rem = compSize[compCnt] << 1, u = i; rem > 0; rem--, u = outIdx[u]) {
          ++cnt[u];
        }
        ++compCnt;
      }
      Arrays.fill(coreSize, 0, compCnt, 0);
      for (int i = 0; i < vertexCnt; ++i) {
        if (cnt[i] <= 1) continue;
        ++coreSize[compIdx[i]];
        distToCore[i] = 0;
        closestCoreNode[i] = i;
      }
      for (int i = 0; i < vertexCnt; ++i) {
        if (distToCore[i] != 0) continue;
        reverseDfs(1, i, i);
      }
      return compCnt;
    }

    private int dfs(int u) {
      if (compIdx[u] >= 0) return 0;
      compIdx[u] = compCnt;
      int res = 1 + dfs(outIdx[u]);
      for (int edgeIdx = lastIn[u]; edgeIdx >= 0; edgeIdx = nextIn[edgeIdx]) {
        res += dfs(fromIdx[edgeIdx]);
      }
      return res;
    }

    private void reverseDfs(int dist, int u, int coreNode) {
      for (int edgeIdx = lastIn[u]; edgeIdx >= 0; edgeIdx = nextIn[edgeIdx]) {
        int v = fromIdx[edgeIdx];
        if (distToCore[v] >= 0) continue;
        distToCore[v] = dist;
        closestCoreNode[v] = coreNode;
        reverseDfs(dist + 1, v, coreNode);
      }
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public QuickWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void print(Object... objects) {
      for (int i = 0; i < objects.length; ++i) {
        if (i > 0) {
          writer.print(' ');
        }
        writer.print(objects[i]);
      }
    }

    public void println(Object... objects) {
      print(objects);
      writer.print('\n');
    }

    public void close() {
      writer.close();
    }

  }

  static class IntUtils {
    private static final int MOD = 1000000007;

    public static int sub(int a, int b) {
      return sub(a, b, MOD);
    }

    public static int sub(int a, int b, int mod) {
      a -= b;
      return a >= 0 ? a + mod : a;
    }

    public static int mul(int a, int b) {
      return mul(a, b, MOD);
    }

    public static int mul(int a, int b, int mod) {
      return a > 0
          ? (
          b < mod / a
              ? a * b
              : (int) ((long) a * b % mod))
          : 0;
    }

    public static int pow(int a, int b) {
      return pow(a, b, MOD);
    }

    public static int pow(int a, int b, int mod) {
      int res = 1;
      for (; b > 0; b >>= 1, a = mul(a, a, mod)) if ((b & 1) > 0) res = mul(res, a);
      return res;
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPostion;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPostion = 0;
      this.numberOfChars = 0;
    }

    public int nextInt() {
      int c = nextNonSpaceChar();
      boolean positive = true;
      if (c == '-') {
        positive = false;
        c = nextChar();
      }
      int res = 0;
      do {
        if (c < '0' || '9' < c) throw new RuntimeException();
        res = res * 10 + c - '0';
        c = nextChar();
      } while (!isSpaceChar(c));
      return positive ? res : -res;
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPostion >= numberOfChars) {
        currentPostion = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPostion++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' '
          || c == '\n'
          || c == '\r'
          || c == '\t'
          || c < 0;
    }

  }

  static class DirectedGraph {
    public int vertexCnt;
    public int edgeCnt;
    public int[] fromIdx;
    public int[] toIdx;
    public int[] nextIn;
    public int[] nextOut;
    public int[] lastIn;
    public int[] lastOut;
    public int[] inDegree;
    public int[] outDegree;

    public DirectedGraph(int vertexCapacity, int edgeCapacity) {
      this.fromIdx = new int[edgeCapacity];
      this.toIdx = new int[edgeCapacity];
      this.lastIn = new int[vertexCapacity];
      this.lastOut = new int[vertexCapacity];
      this.nextIn = new int[edgeCapacity];
      this.nextOut = new int[edgeCapacity];
      this.inDegree = new int[vertexCapacity];
      this.outDegree = new int[vertexCapacity];
    }

    public void init(int vertexCnt) {
      this.vertexCnt = vertexCnt;
      this.edgeCnt = 0;
      Arrays.fill(inDegree, 0, vertexCnt, 0);
      Arrays.fill(outDegree, 0, vertexCnt, 0);
      Arrays.fill(lastIn, 0, vertexCnt, -1);
      Arrays.fill(lastOut, 0, vertexCnt, -1);
    }

    public void add(int fromIdx, int toIdx) {
      this.fromIdx[edgeCnt] = fromIdx;
      this.toIdx[edgeCnt] = toIdx;
      ++outDegree[fromIdx];
      ++inDegree[toIdx];
      nextOut[edgeCnt] = lastOut[fromIdx];
      lastOut[fromIdx] = edgeCnt;
      nextIn[edgeCnt] = lastIn[toIdx];
      lastIn[toIdx] = edgeCnt;
      ++edgeCnt;
    }

  }
}