Language: C++

// #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 EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++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 DB(c) cout<<TO_STRING(c)<<"="<<(c)<<endl

#define EXIST(e,s) ((s).find(e)!=(s).end())
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
#define debug2(x) cerr << #x << " = [";REP(__ind,(x).size()){cerr << (x)[__ind] << ", ";}cerr << "] (L" << __LINE__ << ")" << endl;

#define clr(a) memset((a),0,sizeof(a))
#define nclr(a) memset((a),-1,sizeof(a))
#define pb push_back

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

typedef pair<int,int> pii;
//{{{ io
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,string &s){
    char c;s.clear();
    while(isspace(c=getc(stdin))){if(c==-1)return io;}
    do{
        s.push_back(c);
    }while(!isspace(c=getc(stdin)));
    if(c!=-1)ungetc(c,stdin);
    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;}
IO& operator<<(IO &io,const string &s){
    REP(i,s.size())putc(s[i],stdout);
}
//}}}
// }}}

//{{{ 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
}
//}}}
 
 const int mod = 1000000007;

//{{{ modular algebra
struct Num{
	int v;
	Num(int n):v(n){}
	Num(){}
	operator int() const {return v;}
	operator long long() const {return v;}
	operator =(int n){v=n;}

	template<class T>
	inline void operator *=(const T &a) {
		v = (v*(long long)a)%mod;
	}
	template<class T>
	inline Num operator *(const T &a) {
		Num n(*this);n*=a;
		return n;
	}
	template<class T>
	inline void operator+=(const T &a){
		v+=(int)a;
		if(v>=mod)v-=mod;
		//	assert(0<=v and v<mod);
	}
	template<class T>
	inline Num operator+(const T &a){
		Num n(*this);n+=a;
		return n;
	}
	inline Num operator -(){
		if(v==0)return v;
		else return Num(mod-v);
	}
	template<class T>
	inline void operator -=(const T &a){
		v-=a;
		if(v<0)v+=mod;
	}
	template<class T>
	inline Num operator -(const T &a){
		Num n(*this);n-=a;
		return n;
	}
#ifdef __GCD_H
	inline Num inv(){
		return invMod(this->v,mod);
	}
	template<class T>
	inline void operator /=(const T &a){
		(*this)*=invMod((int)a,mod);
	}
	template<class T>
	inline Num operator /(const T &a){
		Num n(*this);n/=a;
		return n;
	}
#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(__fact.back()*__fact.size());
	return __fact[n];
}
 
inline Num binom(int n,int r){
	if(n<0 or r<0 or n<r)return 0;
	return fact(n)/(fact(r)*fact(n-r));
}
 
inline Num multinom(const vector<int> &v){
	Num num(fact(accumulate(ALL(v),0))), denom(1);
	REP(i,v.size())denom*=fact(v[i]);
	return num/denom;
}
//}}}
 
//{{{ pow
 
/* (x^k)%m */
inline Num powMod(Num x, int k){
	if(k==0) return 1;
	Num res(powMod(x,k/2));
	res*=res;
	if(k%2)res*=x;
	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){
				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++){
			int u = num-t*2;
			if(u<0)break;
			Num b = multinom({t,t,u});
			b*=fact(t);
			b*=powMod(len,t);
			b/=powMod(2,t);
			if(len>1 and len%2==1){
				b*=powMod(2,u);
			}
			s+=b;
		}
		ans*=s;
	}
//	assert(ans!=0);
	cout<<(int)ans<<endl;
	return 0;
}


Compiler output:
a.cc: In function 'IO& operator<<(IO&, const std::string&)':
a.cc:60:1: warning: no return statement in function returning non-void [-Wreturn-type]
   60 | }
      | ^
a.cc: At global scope:
a.cc:94:9: error: ISO C++ forbids declaration of 'operator=' with no type [-fpermissive]
   94 |         operator =(int n){v=n;}
      |         ^~~~~~~~
a.cc: In member function 'int Num::operator=(int)':
a.cc:94:31: warning: no return statement in function returning non-void [-Wreturn-type]
   94 |         operator =(int n){v=n;}
      |                               ^