// #includes {{{
#include<bits/stdc++.h>
using namespace std;
// }}}
// pre-written code {{{
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define RREP(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define IFOR(i,it,c) for(__typeof((c).begin())it=(c).begin();it!=(c).end();++it,++i)
#define ALL(c) (c).begin(), (c).end()
#define MP make_pair
#define PB push_back
#define CLEAR(c,d) memset((c),(d),sizeof(c))
#define TO_STRING(VariableName) # VariableName
#define dump(c) cout<<TO_STRING(c)<<"="<<(c)<<endl

typedef long long Int;
typedef unsigned long long uInt;
typedef long double rn;

typedef pair<int,int> pii;


struct IO{ }io;//dummy
#define endl "\n"
IO& operator>>(IO &io,int &n){scanf("%d",&n);return io;}
IO& operator>>(IO &io,unsigned int &n){scanf("%u",&n);return io;}
IO& operator>>(IO &io,long long &n){scanf("%lld",&n);return io;}
IO& operator>>(IO &io,unsigned long long &n){scanf("%llu",&n);return io;}
IO& operator>>(IO &io,double &n){scanf("%lf",&n);return io;}
IO& operator>>(IO &io,long double &n){scanf("%Lf",&n);return io;}
IO& operator>>(IO &io,char *c){scanf("%s",c);return io;}
 
IO& operator<<(IO &io,const int &n){printf("%d",n);return io;}
IO& operator<<(IO &io,const unsigned int &n){printf("%u",n);return io;}
IO& operator<<(IO &io,const long long &n){printf("%lld",n);return io;}
IO& operator<<(IO &io,const unsigned long long &n){printf("%llu",n);return io;}
IO& operator<<(IO &io,const double &n){printf("%lf",n);return io;}
IO& operator<<(IO &io,const long double &n){printf("%Lf",n);return io;}
IO& operator<<(IO &io,const char c[]){printf("%s",c);return io;}
// }}}

//{{{ gcd and inverse
#define __GCD_H
Int gcd(Int a, Int b) {
	return b != 0 ? gcd(b, a % b) : a;
}
Int lcm(Int a, Int b) {
	return a / gcd(a, b) *b;
}
// a x + b y = gcd(a, b)
Int extgcd(Int a, Int b, Int &x, Int &y) {
	Int g = a; x = 1; y = 0;
	if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x;
	return g;
}
Int invMod(Int a, Int m) {
	Int x, y;
	if (extgcd(a, m, x, y) == 1) return (x + m) % m;
	else                         return 0; // unsolvable
}
//}}}

typedef long long Num;
const Num mod = 1000000007;
//const Num mod = 998244353;

//{{{ operation
inline Num mul(const Num &a, const Num &b, const Num m = mod){
	Num c = (a*(long long)b)%m;
//	assert(0<=c and c<m);
	return c;
}
inline void mul0(Num &a, const Num &b, const Num m = mod){
	a = mul(a,b,m);
}
inline Num add(const Num &a, const Num &b, const Num m = mod){
//	assert(0<=a and a<mod and 0<=b and b<mod);
	Num c=a+b;
	if(c>=m)c-=m;
//	assert(0<=c and c<m);
	return c;
}
inline Num add0(Num &a, const Num &b, const Num m = mod){
	a = add(a,b,m);
}
inline Num neg(const Num &a, const Num m = mod){
	if(a==0)return 0;
	else return m-a;
}
inline Num subt(const Num &a, const Num &b, const Num m = mod){
	Num c = a-b;
	if(c<0)c+=m;
	return c;
}
inline Num subt0(Num &a, const Num &b, const Num m = mod){
	a -= b;
	if(a<0)a+=m;
}
#ifdef __GCD_H
inline Num inv(const Num &a, const Num m = mod){
	return invMod(a,m);
}
inline Num divi(const Num &a, const Num &b, const Num m = mod){
	return mul(a,inv(b,m),m);
}
inline void divi0(Num &a, const Num &b, const Num m = mod){
	a = divi(a,b,m);
}
#endif
//}}}

//{{{ fact, binom, multinom
inline Num fact(int n,const int &mod = mod){
	static vector<Num> __fact(1,1);
	while(n>=__fact.size())__fact.push_back(mul(__fact.back(),__fact.size(),mod));
	return __fact[n];
}

inline Num binom(int n,int r,const int &mod = mod){
	if(n<0 or r<0 or n<r)return 0;
	return divi(fact(n,mod),mul(fact(r,mod),fact(n-r,mod),mod),mod);
}

inline Num multinom(const vector<Num> &v){
	Num num = fact(accumulate(ALL(v),0)), denom = 1;
	REP(i,v.size())mul0(denom,fact(v[i]));
	return divi(num,denom);
}
//}}}

//{{{ pow

//typedef int Num;
//const Num mod = 1000000007;

/* (x^k)%m */
inline Num powMod(Num x, Num k, const Num m = mod){
	if(k==0) return 1;
	Num res = powMod(x,k/2,m);
	mul0(res,res,m);
	if(k%2)mul0(res,x,m);
	return res;
}
//}}}

int N;
int a[100010];

//{{{ graph
typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;
//}}}

//{{{ strong connected components
void visit(const Graph &g, int v, vector< vector<int> >& scc,
		stack<int> &S, vector<bool> &inS,
		vector<int> &low, vector<int> &num, int& time) {
	low[v] = num[v] = ++time;
	S.push(v); inS[v] = true;
	FOR(e, g[v]) {
		int w = e->dst;
		if (num[w] == 0) {
			visit(g, w, scc, S, inS, low, num, time);
			low[v] = min(low[v], low[w]);
		} else if (inS[w])
			low[v] = min(low[v], num[w]);
	}
	if (low[v] == num[v]) {
		scc.push_back(vector<int>());
		while (1) {
			int w = S.top(); S.pop(); inS[w] = false;
			scc.back().push_back(w);
			if (v == w) break;
		}
	}
}
void stronglyConnectedComponents(const Graph& g,
		vector< vector<int> >& scc) {
	scc.clear();
	const int n = g.size();
	vector<int> num(n), low(n);
	stack<int> S;
	vector<bool> inS(n);
	int time = 0;
	REP(u, n) if (num[u] == 0)
		visit(g, u, scc, S, inS, low, num, time);
}
//}}}

int main(){
	cin>>N;
	Graph g(N);
	REP(i,N)cin>>a[i],a[i]--,g[a[i]].push_back(Edge(a[i],i,1));
	vector<vector<int> > scc;
	stronglyConnectedComponents(g,scc);
	Num ans = 1;
	unordered_map<int,int> circle;
	REP(i,scc.size()){
		if(scc[i].size()==1 and a[scc[i][0]]!=scc[i][0])continue;
		int start_u = -1;
		REP(j,scc[i].size()){
			if(g[scc[i][j]].size()>=3){
				cout<<0<<endl;
				return 0;
			}else if(g[scc[i][j]].size()==2){
				start_u = scc[i][j];
				break;
			}
		}
		if(start_u==-1){
			circle[scc[i].size()]++;
			continue;
		}
		set<int> st(ALL(scc[i]));
		vector<pii> v;
		int ct = -1;
		vector<pii> dists;
		for(int u = start_u;;){
			if(g[u].size()==2){
				if(ct!=-1){
					int s;
					s = (st.find(g[u][0].dst)==st.end())?g[u][0].dst:g[u][1].dst;
					int len = 1;
					for(;g[s].size()>=1;){
						if(g[s].size()>=2){
							cout<<0<<endl;
							return 0;
						}
						s = g[s][0].dst;
						len++;
					}
					dists.push_back(make_pair(ct,len));
					if(u==start_u)break;
				}
				ct = 0;
			}
			ct++;
			u = a[u];
		}
		for(auto &a:dists){
			if(a.first<a.second){
				cout<<0<<endl;
				return 0;
			}else if(a.first>a.second){
				mul0(ans,2);
			}
//			cerr<<a.first<<" "<<a.second<<endl;
		}
	}
	for(auto &e:circle){
		int len = e.first, num = e.second;
		Num s = 0;
		for(int t=0;;t++){
			Num u = num-t*2;
			if(u<0)break;
			Num b = multinom({t,t,u});
			mul0(b,fact(t));
			mul0(b,powMod(len,t));
			divi0(b,powMod(2,t));
			if(len>1 and len%2==1){
				mul0(b,powMod(2,u));
			}
			add0(s,b);
		}
		mul0(ans,s);
	}
	assert(ans!=0);
	cout<<ans<<endl;
	return 0;
}

Measured memory_bytes: 25252