#include<bits/stdc++.h>
using namespace std;

#define int long long

#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;

template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

const int mod=1000000007;

int mpow(int n,int m){
    int ret=1;
    while(m){
        if(m&1)ret=ret*n%mod;
        n=n*n%mod;
        m>>=1;
    }
    return ret;
}

const int FACT_SIZE=1111111;
int fact[FACT_SIZE];
int inv[FACT_SIZE];
struct fact_exec{
    fact_exec(){
        fact[0]=1;
        for(int i=1;i<FACT_SIZE;i++)fact[i]=fact[i-1]*i%mod;
        inv[FACT_SIZE-1]=mpow(fact[FACT_SIZE-1],mod-2);
        for(int i=FACT_SIZE-2;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
    }
}factexec;
int nCk(int n,int k){
    return fact[n]*inv[k]%mod*inv[n-k]%mod;
}
int nPk(int n,int k){
    return fact[n]*inv[n-k]%mod;
}


struct UnionFindTree{
    vector<int>par,sz;
    UnionFindTree(int n){
        par.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++){
            par[i]=i;
            sz[i]=1;
        }
    }
    int find(int x){
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        if(sz[x]<sz[y])swap(x,y);
        sz[x]+=sz[y];
        par[y]=x;
    }
    bool areSame(int x,int y){
        return find(x)==find(y);
    }
    int size(int x){
        return sz[find(x)];
    }
};


int N;
int A[111111];
vint lis[111111];

int L[111111];

int deg[111111];
int w[111111];

int calc(vint &vs){
    queue<int>que;
    for(auto u:vs){
        if(deg[u])continue;
        que.push(u);
    }
    while(que.size()){
        int v=que.front();
        que.pop();
        if(w[A[v]]!=0)return 0;
        w[A[v]]+=w[v]+1;
        if(--deg[A[v]]==0)que.push(A[v]);
    }

    int v,g;
    for(auto u:vs)if(deg[u])g=u;
    v=g;
    vint ei;
    while(true){
        ei.pb(v);
        v=A[v];
        if(v==g)break;
    }
    reverse(all(ei));

    if(ei.size()==vs.size()){
        L[vs.size()]++;
        return 1;
    }


    int ret=1;
    for(int i=0;i<ei.size();i++){
        if(w[ei[i]]==0)continue;
        if(w[ei[i]]>ei.size())return 0;

        for(int j=1;j<w[ei[i]];j++)if(w[ei[(i+j)%ei.size()]])return 0;
        if(w[ei[(i+w[ei[i]])%ei.size()]]==0)ret=ret*2%mod;
    }
    return ret;
}

int dp[111111];

signed main(){
    scanf("%lld",&N);
    UnionFindTree uf(N);
    rep(i,N){
        scanf("%lld",&A[i]);
        A[i]--;
        deg[A[i]]++;
        uf.unite(A[i],i);
    }
    rep(i,N){
        if(deg[i]>2){
            cout<<0<<endl;
            return 0;
        }
    }

    rep(i,N){
        lis[uf.find(i)].pb(i);
    }

    int ans=1;

    rep(i,N){
        if(lis[i].size()==0)continue;
        ans=ans*calc(lis[i])%mod;
    }

    for(int i=1;i<=N;i++){
        for(int j=0;j<=L[i];j++)dp[j]=0;
        dp[L[i]]=1;
        for(int j=L[i];j>0;j--){
            dp[j-1]=(dp[j-1]+dp[j]*(1+(i!=1&&i%2)))%mod;
            if(j>1){
                dp[j-2]=(dp[j-2]+dp[j]*(j-1)*i)%mod;
            }
        }
        ans=ans*dp[0]%mod;
    }

    cout<<ans<<endl;
    return 0;
}


Measured memory_bytes: 28288