#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <list>
#include <sstream>
#include <cmath>
#include <functional>
using namespace std;

#define rep(i,n) for(int i=0;i<n;i++)
#define reps(s,i,n) for(int i=s;i<n;i++)
#define rev(i,n) for(int i=n-1;i>=0;i--)
#define skip(i,n,p) for(int i=0;i<n;i+=p)
#define all(a)  (a).begin(),(a).end()
#define int64 long long
#define debug cerr << __FILE__ << ":" << __LINE__ << endl;
#define INF 2147483647

struct Init {
    Init() {
        cin.tie(0);
        ios::sync_with_stdio(false);
        cout.precision(20);
        cout << fixed;
    }
} init;

template <typename _Ty>
ostream& operator << (ostream& ostr, const vector<_Ty>& v) {
    for(int i = 0; i < (int) v.size(); i++) {
        ostr << v[i] << (i + 1 != v.size() ? " " : "");
    }
    return ostr;
}

template <typename _K, typename _V>
ostream& operator << (ostream& ostr, const map<_K, _V>& v) {
    ostr << "{";
    for (auto iter = v.begin(); iter != v.end(); ++iter) {
        ostr << (*iter).first << ": " << (*iter).second << ", ";
    }
    ostr << "}";
    return ostr;
}

template <typename _K>
ostream& operator << (ostream& ostr, const set<_K>& v) {
    for (auto iter = v.begin(); iter != v.end(); ++iter) {
        ostr << *iter << (iter != v.end() ? " " : "");
    }
    return ostr;
}

template <typename _K, typename _V>
ostream& operator << (ostream& ostr, const pair<_K, _V>& v) {
    ostr << v.first << " " << v.second;
    return ostr;
}

int64 gcd(int64 a, int64 b) {
    if (a < b) a, b = b, a;
    if (a % b == 0) return b;
    return gcd(b, a % b);
}

int64 modinv(int64 a, int64 m) {
    int64 b = m, u = 1, v = 0;
    while (b) {
        int64 t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    u %= m;
    if (u < 0) u += m;
    return u;
}

// https://en.wikipedia.org/wiki/Trial_division
map<int64, int64> f(int64 n) {
    map<int64, int64> m;

    while (n % 2 == 0) {
        m[2]++;
        n = n / 2;
    }

    int64 c = 3;
    while (c * c <= n) {
        if (n % c == 0) {
            n = n / c;
            m[c]++;
        } else {
            c += 2;
        }
    }
    if (n != 1) m[n]++;
    return m;
}

template <typename T>
class SegmentTree {
private:
    int n;
    vector<T> data;
    function<T(T, T)> operation;
    function<T(T, T)> change;
public:
    SegmentTree(vector<T> d, function<T(T, T)> _operation, function<T(T, T)> _change)
        : operation(_operation), change(_change) {
        n = 1;
        while (n < d.size()) n *= 2;
        data.resize(n * 2 - 1, INF);

        rep(i, d.size()) data[data.size() - n + i] = d[i];
        rev(i, data.size() - n) data[i] = operation(data[i*2+1], data[i*2+2]);
    }

    void update(int index, T val) {
        index += n - 1;
        data[index] = change(data[index], val);
        while (index != 0) {
            index = (index - 1) / 2;
            data[index] = operation(data[index*2+1], data[index*2+2]);
        }
    }

    T query(int a, int b, int k=0, int l=0, int r=-1) {
        if (r < 0) r = n;
        if (r <= a || b <= l) return INF;
        if (a <= l && r <= b) return data[k];

        T left = query(a, b, k*2+1, l, (l+r)/2);
        T right = query(a, b, k*2+2, (l+r)/2, r);

        return operation(left, right);
    }

    T operator[](int index) {
        return data[index + n - 1];
    }
};

int main() {
    int N; cin >> N;
    vector<int> L(N); rep(i, N) cin >> L[i];

    int ans = 0;
    rep(i, N) {
        if (i == L[L[i]-1]-1) ans++;
    }

    cout << ans/2 << endl;
}


Measured memory_bytes: 640