#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

ll N;
ll in_num[SIZE],in[SIZE][2];
ll POW[SIZE],fact[SIZE];
int table[SIZE],boss[SIZE],height[SIZE],member_num[SIZE];

//scc
vector<int> G[SIZE];
vector<int> reverse_G[SIZE];
stack<int> S;
int group_index;
int scc_NUM[SIZE];

bool check[SIZE];



ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_pow(ll x,ll count, ll mod){

	if(count == 0)return 1;
	ll ret = mod_pow((x*x)%mod,count/2,mod);
	if(count%2 == 1){

		ret = (ret*x)%mod;
	}
	return ret;
}


ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}

ll mod_fact(ll n,ll p,ll &e){
	e = 0;
	if(n == 0)return 1;

	int res = mod_fact(n/p,p,e);
	e += n/p;

	if(n/p%2 != 0)return res*(p-fact[n%p])%p;
	return res*fact[n%p]%p;
}


ll nCm(ll n,ll m,ll p){
   if(n < m) return 0;
   ll e1,e2,e3;
   ll a1 = mod_fact(n,p,e1),a2 = mod_fact(m,p,e2),a3 = mod_fact(n-m,p,e3);
   if(e1 > e2+e3)return 0;
   return a1 * mod_inverse(a2*a3%p,p)%p;
}


int get_boss(int id){
	if(boss[id] == id)return id; //自分が代表なら、自分の値を返す
	else{
		return boss[id] = get_boss(boss[id]); //代表でないなら、自分が所属する組織の代表を返しつつ、経路圧縮
	}
}

int is_same(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[boss_x] > height[boss_y]){

		member_num[boss_x] += member_num[boss_y];
		boss[boss_y] = boss_x;

	}else if(height[boss_x] < height[boss_y]){

		member_num[boss_y] += member_num[boss_x];
		boss[boss_x] = boss_y;

	}else{ //height[boss_x] == height[boss_y]

		member_num[boss_x] += member_num[boss_y];
		boss[boss_y] = boss_x;
		height[x]++;
	}
}

void init(){

	for(int i = 0; i < N; i++){
		boss[i] = i;
		height[i] = 0;
		member_num[i] = 1;
	}
}

void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i]])dfs(G[node_id][i]);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	scc_NUM[group_index]++;

	for(int i = 0; i < reverse_G[node_id].size(); i++){
		if(!check[reverse_G[node_id][i]])reverse_dfs(reverse_G[node_id][i]);
	}
}


void func(){

	for(int i = 0; i < N; i++){

		in_num[i] = 0;
	}
	for(int i = 0; i < N; i++){
		G[i].clear();
		reverse_G[i].clear();
	}

	bool FLG = true;

	for(int i = 0; i < N; i++){

		scanf("%d",&table[i]);
		if(!FLG)continue;

		table[i]--;

		G[i].push_back(table[i]);
		reverse_G[table[i]].push_back(i);

		if(in_num[table[i]] <= 1){

			in[table[i]][in_num[table[i]]] = i;
			in_num[table[i]]++;

		}else{ //入次数3のノード発生

			FLG = false;
		}
	}
	if(!FLG){
		printf("0\n");
		return;
	}
	//入次数が2で、入次ノード以外のノードに出次しているノードがあったら不可
	for(int i = 0; i < N; i++){
		if(in_num[i] < 2)continue;

		if(table[i] != in[i][0] && table[i] != in[i][1]){

			printf("0\n");
			return;
		}
	}

	//閉路チェック
	for(int i = 0; i < N; i++){

		scc_NUM[i] = 0;
		check[i] = false;
	}

	//まずは帰りがけ順を計算
	for(int i = 0; i < N;i++){
		if(!check[i])dfs(i);
	}
	for(int i = 0; i < N;i++)check[i] = false;

	group_index = -1;
	//ノードを、帰りがけ順の逆順に、各強連結成分(グループ)に分解
	while(!S.empty()){
		if(!check[S.top()]){
			group_index++;

			reverse_dfs(S.top());
		}
		S.pop();
	}

	for(int i = 0; i <= group_index; i++){

		//要素数3以上の閉路
		if(scc_NUM[i] >= 3){

			printf("0\n");
			return;
		}
	}

	init();

	for(int i = 0; i < N; i++){

		unite(i,table[i]);
	}

	ll num_2 = 0,num_other = 0;

	for(int i = 0; i < N; i++){
		if(get_boss(i) == i){
			if(member_num[i] == 2){

				num_2++;

			}else{

				num_other++;
			}
		}
	}

	ll ans = 0;

	if(num_other == 0){

		ans = fact[num_2];
		ans *= POW[num_2];
		ans %= MOD;
		ans *= (num_2/2+1);
		ans %= MOD;

		printf("%lld\n",ans);

		return;
	}

	ll BASE = POW[num_2+num_other];

	BASE *= fact[num_2];
	BASE %= MOD;

	BASE *= fact[num_other];
	BASE %= MOD;

	ll A,B;

	for(ll i = 0; i <= num_2; i++){

		A = nCm(num_2+num_other-(i+2),num_2-i,MOD);
		A *= (num_2+num_other-i-1);
		A %= MOD;
		A *= (i/2+1);
		A %= MOD;
		A *= BASE;
		A %= MOD;

		ans += A;
		ans %= MOD;

		B = nCm(num_2+num_other-(i+1),num_2-i,MOD);
		B *= (i/2+1);
		B %= MOD;
		B *= 2;
		B %= MOD;
		B *= BASE;
		B %= MOD;

		ans += B;
		ans %= MOD;
	}
	printf("%lld\n",ans);
}

int main(){

	fact[0] = 1;
	for(ll i = 1; i < SIZE; i++){
		fact[i] = i*fact[i-1];
		fact[i] %= MOD;
	}

	POW[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW[i] = POW[i-1]*2;
		POW[i] %= MOD;
	}

	while(true){
		scanf("%lld",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}



Measured memory_bytes: 20348