// tzl ak IOI! 
 
#include<bits/stdc++.h>
 
#define HEAP priority_queue
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define per(i, n) for(int i = (n) - 1; i >= 0 ; --i)
#define forn(i, l, r) for(int i = (l); i <= (r); ++i)
#define nrof(i, r, l) for(int i = (r); i >= (l); --i)
#define FOR(a, b) for(auto (a): (b))
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define X first
#define Y second
#define eps 1e-6
#define pi 3.1415926535897932384626433832795
#define SZ(x) (int)x.size()
#define ALL(x) x.begin(), x.end()
#define FILL(a, b) memset((a), (b), sizeof((a)))
#define MCPY(a, b) memcpy((a), (b), sizeof((b)))
 
using namespace std;
 
typedef long long LL;
typedef double flt;
typedef vector<int> vi;
typedef vector<LL> vl;
typedef pair<int,int> pii;
typedef pair<int,LL> pil;
typedef pair<LL,int> pli;
typedef pair<LL,LL> pll;
typedef vector<pil> vil;
typedef vector<pii> vii;
typedef vector<pli> vli;
typedef vector<pll> vll;
 
const int iinf = 1e9 + 7;
const LL linf = 1ll << 60;
const flt dinf = 1e60;
 
template <typename T>
inline void scf(T &x)
{
	bool f = 0; x = 0; char c = getchar();
	while((c < '0' || c > '9') && c != '-') c = getchar();
	if(c == '-') { f = 1; c = getchar(); }
	while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
	if(f) x = -x; return;
}
 
template <typename T1, typename T2>
void scf(T1 &x, T2 &y) { scf(x); return scf(y); }
 
template <typename T1, typename T2, typename T3>
void scf(T1 &x, T2 &y, T3 &z) { scf(x); scf(y); return scf(z); }
 
template <typename T1, typename T2, typename T3, typename T4>
void scf(T1 &x, T2 &y, T3 &z, T4 &w) { scf(x); scf(y); scf(z); return scf(w); }
 
inline char mygetchar(){ char c = getchar(); while(c == ' ' || c == '\n') c = getchar(); return c; }
 
template <typename T>
void chkmax(T &x, const T &y){ if(y > x) x = y; return; }
 
template <typename T>
void chkmin(T &x, const T &y){ if(y < x) x = y; return; }
 
#define ONLINE_JUDGE
 
#ifdef ONLINE_JUDGE
#define debug(x,c) ;
#else
#define DEBUG
#define debug(x,c) cerr<<#x<<"="<<x<<c;
#endif
 
//---------------------------head----------------------------
 
using di = deque<int>;
 
const int N = 1e5 + 100;
const LL mod = 1e9 + 7ll;
 
int n, m;
int g[N];
LL fac[N], inv[N];
bool vis[N];
vi rg[N];
LL ans = 1ll;
 
LL INV(LL x)
{
	LL ret = 1ll, n = mod - 2;
	while(n)
	{
		if(n & 1) (ret *= x) %= mod;
		(x *= x) %= mod;
		n >>= 1;
	}
	return ret;
}
 
LL C(LL n, LL m)
{
	if(n < 0 || m < 0 || n - m < 0) return 0;
	return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
 
struct tree
{
	int n;
	di path;
	vector<di> has;
 
	void dfs(int u, di &cur)
	{
		if(SZ(cur) && g[u] != cur.back()){ puts("0"); exit(0); }
		cur.pb(u); vis[u] = 1;
		for(int v: rg[u]) if(!vis[v]) dfs(v, cur);
		return;
	}
 
	void get(int u)
	{
		path.clear();
		while(!vis[u]) vis[u] = 1, path.pb(u), u = g[u];
 
		for(int u: path) vis[u] = 0;
		
		while(path[0] != g[path.back()]) path.pop_front();
 
		has.resize(n = SZ(path));
		for(int u: path) vis[u] = 1;
		rep(i, SZ(path)) dfs(path[i], has[i]), has[i].pop_front();
		return;
	}
 
	void solve()
	{
		LL res = 1ll;
		vi sz(n);
		rep(i, n) sz[i] = SZ(has[i]);
 
		rep(i, n) if(sz[i])
		{
			int j = (i + n - 1) % n, dst = 1;
			while(!sz[j]) j = (j + n - 1) % n, dst++;
			if(dst > sz[i]) (res *= 2ll) %= mod;
			if(dst < sz[i]){ puts("0"); exit(0); }
		}
 
		(ans *= res) %= mod;
		return;
	}
 
	void out()
	{
		puts("_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_");
		printf("%d\n", n);
		for(int u: path) printf("%d ", u); puts("");
		rep(i, n)
		{
			printf("%d:\t", path[i]); for(int v: has[i]) printf("%d ", v); puts("");
		}
		return;
	}
}a[N];
 
struct cyc
{
	int n;
	di path;
 
	void dfs(int u)
	{
		path.pb(u); vis[u] = 1;
		if(!vis[g[u]]) dfs(g[u]);
		return;
	}
 
	void get(int u)
	{
		path.clear();
		dfs(u);
		n = SZ(path);
		return;
	}
}b[N];
 
vi has[N];
LL dp[N];
 
void TZL()
{
	scf(n);
	forn(i, 1, n) scf(g[i]), rg[g[i]].pb(i);
	forn(i, 1, n) if(SZ(rg[i]) > 2){ puts("0"); exit(0); }
 
	dp[2] = dp[0] = 1ll;
	for(int i = 4; i <= n; i += 2) dp[i] = (dp[i - 2] + dp[i - 4] * (LL)(i - 2) % mod * (LL)(i - 3)) % mod;
 
	fac[0] = 1ll; forn(i, 1, n) fac[i] = 1ll * i * fac[i - 1] % mod;
	forn(i, 0, n) inv[i] = INV(fac[i]);
 
	int foo = 0, bar = 0;
	forn(i, 1, n) if(!SZ(rg[i]) && !vis[i]) a[(++foo)].get(i);
	forn(i, 1, n) if(!vis[i]) b[(++bar)].get(i), has[b[bar].n].pb(bar);
	n = foo; m = bar;
	return;
}
 
namespace CYC
{
	void solve(int len)
	{
		int n = SZ(has[len]);
		LL p = ((len & 1) && len != 1) ? 2ll : 1ll, ip = INV(p);
		LL l = 1ll;
		if(p > 1ll) rep(i, n - 1) (p *= 2ll) %= mod;
 
		LL res = 0ll;
		for(int i = 0; i <= n; i += 2)
		{
			(res += p * l % mod * C(n, i) % mod * dp[i] % mod) %= mod;
			(p *= ip) %= mod;
			(p *= ip) %= mod;
			(l *= (LL)len) %= mod;
		}
 
		(ans *= res) %= mod;
		return;
	}
}
 
void RANK1()
{
	rep(i, N) if(SZ(has[i])) CYC::solve(i);
	forn(i, 1, n) a[i].solve();
	printf("%lld\n", ans);
	return;
}
 
#define tzl int
#define ak main
#define IOI ()
tzl ak IOI
{
#undef tzl
#undef ak
#undef IOI
 
	TZL();
	RANK1();
 
#define tzl return
#define caisi 0
#define myy ;
	tzl caisi myy
#undef tzl
#undef caisi
#undef myy
}

Measured memory_bytes: 217344