#include<bits/stdc++.h>
#define REP(i,m) for(int i=0;i<(m);++i)
#define REPN(i,m,in) for(int i=(in);i<(m);++i)
#define ALL(t) (t).begin(),(t).end()
#define CLR(a) memset((a),0,sizeof(a))
#define pb push_back
#define mp make_pair
#define fr first
#define sc second

using namespace std;


#ifdef DEB
#define dump(x)  cerr << #x << " = " << (x) << endl
#define prl cerr<<"called:"<< __LINE__<<endl
#define dumpR(x) cerr<<"\x1b[31m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
#define dumpY(x) cerr<<"\x1b[33m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
#define dumpG(x) cerr<<"\x1b[32m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
template<class T> void debug(T a,T b){ for(;a!=b;++a) cerr<<*a<<' ';cerr<<endl;}
#else
#define dump(x) ;
#define dumpR(x) ;
#define dumpY(x) ;
#define dumpG(x) ;
#define prl ;
template<class T> void debug(T a,T b){ ;}
#endif

template<class T> void chmin(T& a,const T& b) { if(a>b) a=b; }
template<class T> void chmax(T& a,const T& b) { if(a<b) a=b; }

typedef long long int lint;
typedef pair<int,int> pi;

namespace std{
  template<class S,class T>
  ostream &operator <<(ostream& out,const pair<S,T>& a){
    out<<'('<<a.fr<<','<<a.sc<<')';
    return out;
  }
}

//const int INF=5e8;
struct uf{

  static const int MAXN=100005;
  int par[MAXN];
  int size[MAXN];
  void init(){
    memset(par,-1,sizeof(par));
    REP(i,MAXN) size[i]=1;
  }
  int root(int a){
    if(par[a]==-1) return a;
    return par[a]=root(par[a]);
  }
  void unite(int a,int b){
    a=root(a);b=root(b);
    if(a==b) return;
    if(size[a]<size[b]) swap(a,b);

    par[b]=a;
    size[a]+=size[b];
  }
  bool same(int a,int b){
    return root(a)==root(b);
  }
};

template<lint mod>
struct Int_{
  unsigned x;
  unsigned mpow(Int_ a,unsigned k){
    Int_ res=1;
    while(k){
      if(k&1) res=res*a;
      a=a*a;
      k>>=1;
    }
    return res.x;
  }
  unsigned inverse(Int_ a){
    return mpow(a,mod-2);
  }
  Int_(): x(0) { }
  Int_(long long sig) {
    int sigt=sig%mod;
    if(sigt<0) sigt+=mod;
    x=sigt;
  }
  unsigned get() const { return (unsigned)x; }
  
  Int_ &operator+=(Int_ that) { if((x += that.x) >= mod) x -= mod; return *this; }
  Int_ &operator-=(Int_ that) { if((x += mod - that.x) >= mod) x -= mod; return *this; }
  Int_ &operator*=(Int_ that) { x = (unsigned long long)x * that.x % mod; return *this; }
  Int_ &operator=(Int_ that) { x=that.x; return *this;}
  Int_ &operator/=(Int_ that) { x=(unsigned long long) x * inverse(that.x)%mod; return *this;}
  bool operator==(Int_ that) const { return x==that.x; }
  bool operator!=(Int_ that) const { return x!=that.x; }

  Int_ operator-() const { return Int_(0)-Int_(*this);}
  Int_ operator+(Int_ that) const { return Int_(*this) += that; }
  Int_ operator-(Int_ that) const { return Int_(*this) -= that; }
  Int_ operator*(Int_ that) const { return Int_(*this) *= that; }
  Int_ operator/(Int_ that) const { return Int_(*this) /= that; }

};

namespace std{
  template<lint mod>
  ostream &operator <<(ostream& out,const Int_<mod>& a){
    out<<a.get();
    return out;
  }
  template<lint mod>
  istream &operator >>(istream& in,Int_<mod>& a){
    in>>a.x;
    return in;
  }
};

typedef Int_<1000000007> Int;
void ng(){
  puts("0");
  exit(0);
}

uf u;

int n;
int ar[100005];
typedef vector<int> vi;
vi ever,cy;

bool vis[100005];
void findcy(int v){
  if(vis[v]){
    cy=ever;
    cy.erase(cy.begin(),find(ALL(cy),v));
    return;
  }
  ever.pb(v);
  vis[v]=1;
  findcy(ar[v]);
}
bool incy[100005];

vi cys[100005];
vi rg[100005];
int simcycnt[100005];

Int solve(vi cy){
  int m=cy.size();
  vi lens(m);
  REP(i,m){
    int v=cy[i];
    while(rg[v].size()==1){
      ++lens[i];
      v=rg[v][0];
    }
  }
  REP(i,m) REPN(j,lens[i],1) if(rg[cy[(i-j+m)%m]].size()) ng();

  Int res=1;
  REP(i,m) if(rg[cy[i]].size()){
    if(rg[cy[(i-lens[i]+m)%m]].size()==0) res*=2;
  }
  return res;
}

Int fact[100005],invf[100005],odf[100005];

Int C(int a,int b){
  if(b>a || a<0 || b<0) return 0;
  return fact[a]*invf[b]*invf[a-b];
}
Int mpow(Int a,unsigned k){
  Int res=1;
  while(k){
    if(k&1) res=res*a;
    a=a*a;
    k>>=1;
  }
  return res.x;
}
int main(){
  cin>>n;
  fact[0]=odf[0]=1;
  REP(i,n){
    fact[i+1]=fact[i]*(i+1);
    odf[i+1]=odf[i]*((i+1)&1?(i+1):1);
  }

  Int one=1;
  invf[n]=one/fact[n];
  for(int i=n-1;i>=0;--i) invf[i]=invf[i+1]*(i+1);

  u.init();
  REP(i,n){
    cin>>ar[i],--ar[i];
    u.unite(i,ar[i]);
  }

  REP(i,n) if(u.root(i)==i){
    ever.clear();
    findcy(i);
    for(auto v:cy) incy[v]=1;
    debug(ALL(cy));
    cys[i]=cy;
  }

  REP(i,n) if(!incy[i] || !incy[ar[i]]){
    rg[ar[i]].pb(i);
  }
  REP(i,n) if(rg[i].size()>1) ng();
  Int res=1;
  REP(i,n) if(u.root(i)==i){
    bool simple=true;
    for(auto v:cys[i]) if(rg[v].size()) simple=false;
    if(simple){
      simcycnt[cys[i].size()]++;
    }else{
      debug(ALL(cys[i]));
      res*=solve(cys[i]);
    }
  }
  dump(res);
  REP(i,n+1) if(simcycnt[i]){
    int a=simcycnt[i];
    dump(i);dump(a);
    Int sum=0;
    for(int j=0;j<=a;j+=2){
      Int pat=C(a,j)*odf[j]*mpow(i,j/2);
      if(i&1 && i>1) pat*=mpow(2,a-j);
      dump(pat);
      sum+=pat;
    }
    res*=sum;
  }
  cout<<res<<endl;
  return 0;
}





Measured memory_bytes: 13048