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

#define rep(i,n) for(int i = 0; i < n; i++)
#define Rep(i,n) for(int i = 1; i <= n; i++)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define fin(a) { cout << a << endl; return 0; }
#define debug(a) { cerr << #a << ": " << a << endl; }
#define endl '\n'
#define fi first
#define se second
using lint = long long;
using ld = long double;
using P = pair<int,int>;
using Pl = pair<lint,lint>;
template<class T> using V = vector<T>;
template<class T> using priq     = priority_queue<T>;
template<class T> using priq_inv = priority_queue<T, vector<T>, greater<T>>;
const int dx[] = {0,1,0,-1,1,1,-1,-1};
const int dy[] = {1,0,-1,0,1,-1,-1,1};
template<class T> T ceil(const T &a, const T &b) { return ((a)+(b)-1)/b; }
template<class T> bool chmin(T &a, T b) { if(a > b) { a = b; return 1; } return 0; }
template<class T> bool chmax(T &a, T b) { if(a < b) { a = b; return 1; } return 0; }
template<class T> void YesorNo(T x) { printf(x ? "Yes\n" : "No\n"); }
struct INF { template<class T> operator T() { return numeric_limits<T>::max() / 2; } } INF;

template<class T, class U> istream& operator>>(istream &in, pair<T,U> &p) {
    return in >> p.first >> p.second;
}
template<class T, class U> ostream& operator<<(ostream &out, const pair<T,U> &p) {
    return out << '{' << p.first << ',' << p.second << '}';
}
template<class T> istream& operator>>(istream &in, vector<T> &v) {
    for(auto &&e : v) in >> e;
    return in;
}
template<class T> ostream& operator<<(ostream &out, const vector<T> &v) {
    for(const auto &e : v) out << e << ' ';
    return out;
}

/*----------------------------------------------------------------------------------------------------*/


struct UnionFind { // UnionFindTree

    vector<int> d;
    int group;
    UnionFind(int n): d(n,-1), group(n) {}

    int find(int x) {
        if(d[x] < 0) return x;
        return d[x] = find(d[x]);
    }

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if(x == y) return false;
        if(-d[x] < -d[y]) swap(x,y);
        group--;
        d[x] += d[y];
        d[y] = x;
        return true;
    }

    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return -d[find(x)]; }
};


long long Modpow(long long a, int n, long long mod){
    if(n == 0) return 1;
    if(n%2 == 0){
      long long res = Modpow(a, n/2, mod);
      return res * res % mod;
    }
    return a * Modpow(a, n-1, mod) % mod;
}


int main(){
    int n;
    cin >> n;
    UnionFind uf(n);
    rep(i,n) {
        int a;
        cin >> a;
        a--;
        uf.unite(i,a);
    }
    cout << Modpow(2,uf.group,998244353)-1 << endl;
}
#include<bits/stdc++.h>
#define re register int
#define ll long long
#define dl long double
#define LL ll
#define V inline void
#define I inline int
#define FOR(i,a,b) for(re i=(a),i##i=(b);i<=i##i;++i)
#define ROF(i,a,b) for(re i=(a),i##i=(b);i>=i##i;--i)
#define gc getchar()
//#define gc (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<18,stdin),fs==ft))?0:*fs++
using namespace std;
char *fs,*ft,buf[1<<18];
const int N=3e5+10,mo=998244353,G=3;
LL read(){
	ll p=0; bool w=0; char ch=gc;
	while(!isdigit(ch)) w=ch=='-',ch=gc;
	while(isdigit(ch)) p=p*10+ch-'0',ch=gc;
	return w?-p:p;
}
int n,f[N],vis[N],as;
ll ans;
LL Pow(ll x,ll y){ ll as=1; for(;y;y>>=1,x=x*x%mo) if(y&1) as=as*x%mo; return as;}
V dfs(int u){
	if(vis[u]) return ;
	vis[u]=1;
	dfs(f[u]);
}
int low[N],dfn[N],now,cnt,id,s[N],bk[N],scc[N],siz[N];
V tarjan(int u){
	s[++cnt]=u;
	low[u]=dfn[u]=++now;
	bk[u]=1;
	int v=f[u];
	if(!low[v]) tarjan(v),low[u]=min(low[u],low[v]);
	else if(bk[v]) low[u]=min(low[u],dfn[v]);
	if(low[u]==dfn[u]){
		scc[u]=++id,siz[id]=1;
		bk[u]=0;
		while(s[cnt]!=u){
			v=s[cnt];
			scc[v]=id,++siz[id];
			bk[v]=0;
			--cnt;
		}--cnt;
	}	
	
}
V sol(){
	FOR(i,1,n) if(!dfn[i]) tarjan(i);
	FOR(i,1,id) if(siz[i]>1) ++as;
	FOR(i,1,n) if(f[i]==i) ++as;
	ans=Pow(2,as)-1;
	cout<<ans;
	return ;
}
int main(){
	n=read();
	FOR(i,1,n) f[i]=read();
	sol();	
	
	return 0;
}