Problem:
F: Invariant Tree
Problem Statement
You have a permutation
p_1, p_2, ... , p_N
of integers from
1
to
N
. You also have vertices numbered
1
through
N
. Find the number of trees while satisfying the following condition. Here, two trees
T
and
T'
are different if and only if there is a pair of vertices where
T
has an edge between them but
T’
does not have an edge between them.
For all integer pairs
i, j
(
1\leq i < j \leq N
), if there is an edge between vertices
i
and
j
, there is an edge between vertices
p_i
and
p_j
as well.
Since this number can be extremely large, output the number modulo
998244353
.
Input
N
p_1
p_2
...
p_N
Constraints
1\leq N \leq 3 \times 10^5
p_1, p_2, ... , p_N
is a permutation of integers
1
through
N
.
Output
Output the number in a single line.
Sample Input 1
4
2 1 4 3
Output for Sample Input 1
4
Let
(u, v)
denote that there is an edge between
u
and
v
. The following
4
ways can make a tree satisfying the condition.
(
1, 2
), (
1, 3
), (
2, 4
)
(
1, 2
), (
1, 4
), (
2, 3
)
(
1, 3
), (
2, 4
), (
3, 4
)
(
1, 4
), (
2, 3
), (
3, 4
)
Sample Input 2
3
1 2 3
Output for Sample Input 2
3
Sample Input 3
3
2 3 1
Output for Sample Input 3
0
Sample Input 4
20
9 2 15 16 5 13 11 18 1 10 7 3 6 14 12 4 20 19 8 17
Output for Sample Input 4
98344960

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using LL = long long;

namespace FastIO {
    char gc() {
        static char buf[1 << 20], *p1, *p2;
        if (p1 == p2) p1 = buf, p2 = buf + fread(buf, 1, 1 << 20, stdin);
        return p1 == p2 ? EOF : *(p1++);
    }
    char readch() {
        char ch;
        do ch = gc(); while (ch <= 32 || ch >= 127);
        return ch;
    }
    template <typename T> void read(T &x) {
        char ch; bool op = 0; x = 0;
        do ch = gc(), op |= ch == '-'; while (ch < '0' || ch > '9');
        do x = x * 10 + (ch & 15), ch = gc(); while (ch >= '0' && ch <= '9');
        if (op) x = -x;
    }
    void read(string &x) {
        char ch; x = "";
        do ch = gc(); while (ch <= 32 || ch >= 127);
        do x += ch, ch = gc(); while (ch > 32 && ch < 127);
    }
    template <typename T, typename...U> void read(T &x, U &...y) { read(x), read(y...); }
    template <typename T> void write(T x, char ed = '\n') {
        static int stk[100]; int tp = 0;
        if (x < 0) putchar('-'), x = -x;
        do stk[++tp] = x % 10, x /= 10; while (x);
        for (; tp; --tp) putchar(stk[tp] | 48);
        putchar(ed);
    }
    template <typename T, typename...U> void write(T x, U ...y) { write(x, ' '), write(y...); }
}
using namespace FastIO;

const int mod = 998244353;
inline int fplus(int x, int y) {return x + y >= mod ? x + y - mod : x + y;}
inline int Fplus(int&x, int y) {return x = fplus(x, y);}
inline int fminus(int x, int y) {return x - y < 0 ? x - y + mod : x - y;}
inline int Fminus(int&x, int y) {return x = fminus(x, y);}
inline int qpow(int x, int y) {
    int res = 1;
    if (y < 0) y += mod - 1;
    for (; y; y >>= 1, x = 1ll * x * x % mod) if (y & 1) res = 1ll * res * x % mod;
    return res;
}

const int MAXN = 1e6+5;

int solve(int n, vector<int> &a) {
    int mul = 1, st = 0;
    if (a[1]) {
        mul = qpow(a[1], a[1] - 2), st = 1;
    } else if (a[2]) {
        mul = qpow(a[2] * 2ll % mod, a[2] - 1), st = 2;
    } else return 0;
    vector<int> t(n + 1);
    for (int x = 1; x <= n; ++x) {
        for (int y = x << 1; y <= n; y += x) t[y] += a[x] * x;
    }
    for (int x = st + 1; x <= n; ++x) {
        if (a[x]) mul = (LL)mul * t[x] % mod * qpow(((LL)a[x] * x + t[x]) % mod, a[x] - 1) % mod;
    }
    return mul;
}


int main() {
    int n;
    read(n);
    vector<int> p(n + 1), vis(n + 1), c(n + 1);
    for (int i = 1; i <= n; ++i) read(p[i]);
    for (int x = 1; x <= n; ++x) {
        if (vis[x]) continue;
        int len = 0;
        for (int y = x; !vis[y]; y = p[y]) len += vis[y] = 1;
        ++c[len];
    }
    write(solve(n, c));
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 8856
final_rank: 2

code_snippet: #include <bits/stdc++.h>

namespace IO
{
char gc()
{
#ifdef FREAD
	static char buf[1<<21], *P1 = buf, *P2 = buf;
	if(P1 == P2)
	{
		P1 = buf;
		P2 = buf + fread(buf, 1, 1<<21, stdin);
		if(P1 == P2) return EOF;
	}
	return *(P1++);
#else
	return getchar();
#endif
}
template<typename Tp> bool get1(Tp &x)
{
	bool neg = 0;
	char c = gc();
	while( c != EOF && (c < '0' || c > '9') && c != '-' ) c = gc();
	if(c == '-') c = gc(), neg = 1;
	if(c == EOF) return false;
	x = 0;
	for(; c>='0' && c<='9'; c = gc()) x = x*10 + c - '0';
	if(neg) x = -x;
	return true;
}
template<typename Tp> void printendl(Tp x)
{
	if(x<0)putchar('-'),x=-x;
	static short a[40], sz;
	sz = 0;
	while(x>0)a[sz++]=x%10,x/=10;
	if(sz==0)putchar('0');
	for(int i=sz-1; i>=0; i--)putchar('0'+a[i]);
	puts("");
}
} // namespace IO
using IO::get1;
using IO::printendl;
#define get2(x,y) get1(x) && get1(y)
#define get3(x,y,z) get2(x,y) && get1(z)
#define get4(x,y,z,w) get3(x,y,z) && get1(w)
#define pb push_back
#define mp std::make_pair
#define ff first
#define ss second
typedef long long LL;
typedef unsigned long long uLL;
typedef std::pair<int,int> pii;
const int inf = 0x3f3f3f3f;
const LL Linf = 1ll<<61;

const int maxn = 300111;
const int mod = 998244353;
int qpow(int x, int y)
{
	if(y < 0) y += mod-1;
	int ret = 1;
	while(y)
	{
		if(y&1) ret = 1ll * ret * x % mod;
		x = 1ll * x * x % mod;
		y >>= 1;
	}
	return ret;
}

std::vector<int> divisor[maxn];
int n, p[maxn], c[maxn], fac[maxn], invf[maxn];
bool use[maxn];

int comb(int x, int y) { return 1ll * fac[x] * invf[y] % mod * invf[x-y] % mod; }

int main()
{
	fac[0] = 1; for(int i=1; i<maxn; i++) fac[i] = 1ll * i * fac[i-1] % mod;
	invf[maxn-1] = qpow(fac[maxn-1], mod-2); for(int i=maxn-1; i>=1; i--) invf[i-1] = 1ll * i * invf[i] % mod;
	get1(n);
	for(int i=1; i<=n; i++) get1(p[i]);
	for(int i=1; i<=n; i++) if(!use[i])
	{
		int cnt = 0, tmp = i;
		while(!use[tmp])
		{
			use[tmp] = 1;
			tmp = p[tmp];
			cnt++;
		}
		c[cnt]++;
	}
	
	for(int i=1; i<=n; i++) for(int j=i+i; j<=n; j+=i) divisor[j].pb(i);
	
	if(c[1])
	{
		int ans = qpow(c[1], c[1]-2);
		for(int i=2; i<=n; i++) if(c[i])
		{
			int coef = 0, sum = 0;
			for(auto v:divisor[i]) coef = (coef + 1ll * v * c[v]) % mod;
			for(int j=1; j<=c[i]; j++)
			{
				int cur = 1ll * qpow(coef, j) * qpow(i, c[i]-j) % mod * j % mod * qpow(c[i], c[i]-j-1) % mod * comb(c[i], j) % mod;
				sum += cur;
				if(sum >= mod) sum -= mod;
			}
			ans = 1ll * ans * sum % mod;
		}
		printendl(ans);
	}
	else if(c[2])
	{
		int ans = 1ll * qpow(c[2], c[2]-2) % mod * c[2] % mod * qpow(2, c[2]-1) % mod;
		for(int i=3; i<=n; i++) if(c[i])
		{
			int coef = 0, sum = 0;
			for(auto v:divisor[i]) coef = (coef + 1ll * v * c[v]) % mod;
			for(int j=1; j<=c[i]; j++)
			{
				int cur = 1ll * qpow(coef, j) * qpow(i, c[i]-j) % mod * j % mod * qpow(c[i], c[i]-j-1) % mod * comb(c[i], j) % mod;
				sum += cur;
				if(sum >= mod) sum -= mod;
			}
			ans = 1ll * ans * sum % mod;
		}
		printendl(ans);
	}
	else puts("0");
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 41024
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i=0; i<(int)(n); i++)
using ll = long long;

const int mod = 998244353;
struct mint {
  unsigned int x;
  mint() : x(0) {}
  mint(ll a) : x(a%mod+mod) { if(x >= mod) x -= mod; }
  int val(){ return x; }
  mint& operator+=(mint r){ x += r.x; if(x >= mod){ x -= mod; } return *this; }
  mint& operator-=(mint r){ x += mod - r.x; if(x >= mod){ x -= mod; } return *this; }
  mint& operator*=(mint r){ x = ll(x) * r.x % mod; return *this; }
  mint& operator/=(mint r){ x = ll(x) * r.inv().x % mod; return *this; }
  friend mint operator+(mint l, mint r){ return l += r; }
  friend mint operator-(mint l, mint r){ return l -= r; }
  friend mint operator*(mint l, mint r){ return l *= r; }
  friend mint operator/(mint l, mint r){ return l /= r; }
  mint pow(ll i) const {
    mint a = 1, r = *this;
    while(i){
      if(i%2) a *= r;
      r *= r; i /= 2;
    }
    return a;
  }
  mint inv() const { return pow(mod-2); }
};

using Mi = mint;

void testcase(){
    int N; cin >> N;
    vector<Mi> buf(N+1, 1);
    vector<int> A(N); rep(i,N) cin >> A[i];
    rep(i,N) A[i]--;
    vector<int> cycnt(N+1), vis(N);
    rep(i,N) if(!vis[i]){
        int n = 0;
        for(int p=i; !vis[p]; p=A[p]){ n++; vis[p]=1; }
        cycnt[n]++;
    }
    vector<Mi> F(N+1, 1); rep(i,N) F[i+1] = F[i] * (i+1);
    auto comb = [&](int n, int r){ return F[n] / (F[r]*F[n-r]); };
    vector<int> cylens;
    rep(i,N+1) if(cycnt[i]) cylens.push_back(i);
    int rt = cylens[0];
    if(rt >= 3){ cout << "0\n"; return; }
    for(int a : cylens){
        int K = cycnt[a];
        if(a == rt){
            buf[a] = Mi(K).pow(K-2) * Mi(a).pow(K-1);
            if(a == 2) buf[a] *= Mi(K);
        } else {
            Mi B = 0;
            for(int b : cylens) if(b < a && a%b == 0){
                B += Mi(b) * cycnt[b];
            }
            buf[a] = 0;
            for(int s=1; s<=K; s++){
                buf[a] += B.pow(s) * comb(K-1,s-1) * Mi(K).pow(K-s) * Mi(a).pow(K-s);
            } 
        }
    }
    Mi ans = 1;
    rep(i,N+1) ans *= buf[i];
    cout << ans.val() << "\n";
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 8904
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i=0; i<(int)(n); i++)
using ll = long long;

const int mod = 998244353;
struct mint {
  unsigned int x;
  mint() : x(0) {}
  mint(ll a) : x(a%mod+mod) { if(x >= mod) x -= mod; }
  int val(){ return x; }
  mint& operator+=(mint r){ x += r.x; if(x >= mod){ x -= mod; } return *this; }
  mint& operator-=(mint r){ x += mod - r.x; if(x >= mod){ x -= mod; } return *this; }
  mint& operator*=(mint r){ x = ll(x) * r.x % mod; return *this; }
  mint& operator/=(mint r){ x = ll(x) * r.inv().x % mod; return *this; }
  friend mint operator+(mint l, mint r){ return l += r; }
  friend mint operator-(mint l, mint r){ return l -= r; }
  friend mint operator*(mint l, mint r){ return l *= r; }
  friend mint operator/(mint l, mint r){ return l /= r; }
  mint pow(ll i) const {
    mint a = 1, r = *this;
    while(i){
      if(i%2) a *= r;
      r *= r; i /= 2;
    }
    return a;
  }
  mint inv() const { return pow(mod-2); }
};

using Mi = mint;

void testcase(){
    int N; cin >> N;
    vector<Mi> buf(N+1, 1);
    vector<int> A(N); rep(i,N) cin >> A[i];
    rep(i,N) A[i]--;
    vector<int> cycnt(N+1), vis(N);
    rep(i,N) if(!vis[i]){
        int n = 0;
        for(int p=i; !vis[p]; p=A[p]){ n++; vis[p]=1; }
        cycnt[n]++;
    }
    vector<Mi> F(N+1, 1); rep(i,N) F[i+1] = F[i] * (i+1);
    auto comb = [&](int n, int r){ return F[n] / (F[r]*F[n-r]); };
    vector<int> cylens;
    rep(i,N+1) if(cycnt[i]) cylens.push_back(i);
    int rt = cylens[0];
    if(rt >= 3){ cout << "0\n"; return; }
    for(int a : cylens){
        int K = cycnt[a];
        if(a == rt){
            buf[a] = Mi(K).pow(K-2) * Mi(a).pow(K);
        } else {
            Mi B = 0;
            for(int b : cylens) if(b < a && a%b == 0){
                B += Mi(b) * cycnt[b];
            }
            buf[a] = 0;
            for(int s=1; s<=K; s++){
                buf[a] += B.pow(s) * comb(K-1,s-1) * Mi(K).pow(K-s) * Mi(a).pow(K-s);
            } 
        }
    }
    Mi ans = 1;
    rep(i,N+1) ans *= buf[i];
    cout << ans.val() << "\n";
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    testcase();
    return 0;
}
accuracy: 0.3
time_ms: 20
memory_kb: 8860
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <cassert>
using namespace std;
#define rep(i,n) for(int i=0; i<(int)(n); i++)
using ll = long long;

const int mod = 998244353;
struct mint {
  unsigned int x;
  mint() : x(0) {}
  mint(ll a) : x(a%mod+mod) { if(x >= mod) x -= mod; }
  int val(){ return x; }
  mint& operator+=(mint r){ x += r.x; if(x >= mod){ x -= mod; } return *this; }
  mint& operator-=(mint r){ x += mod - r.x; if(x >= mod){ x -= mod; } return *this; }
  mint& operator*=(mint r){ x = ll(x) * r.x % mod; return *this; }
  mint& operator/=(mint r){ x = ll(x) * r.inv().x % mod; return *this; }
  friend mint operator+(mint l, mint r){ return l += r; }
  friend mint operator-(mint l, mint r){ return l -= r; }
  friend mint operator*(mint l, mint r){ return l *= r; }
  friend mint operator/(mint l, mint r){ return l /= r; }
  mint pow(ll i) const {
    mint a = 1, r = *this;
    while(i){
      if(i%2) a *= r;
      r *= r; i /= 2;
    }
    return a;
  }
  mint inv() const { return pow(mod-2); }
};

using Mi = mint;

void testcase(){
    int N; cin >> N;
    vector<Mi> buf(N+1, 1);
    vector<int> A(N); rep(i,N) cin >> A[i];
    rep(i,N) A[i]--;
    vector<int> cycnt(N+1), vis(N);
    rep(i,N) if(!vis[i]){
        int n = 0;
        for(int p=i; !vis[p]; p=A[p]){ n++; vis[p]=1; }
        cycnt[n]++;
    }
    vector<Mi> F(N+1, 1); rep(i,N) F[i+1] = F[i] * (i+1);
    auto comb = [&](int n, int r){ return F[n] / (F[r]*F[n-r]); };
    vector<int> cylens;
    rep(i,N+1) if(cycnt[i]) cylens.push_back(i);
    int rt = cylens[0];
    if(rt >= 3){ cout << "0\n"; return; }
    for(int a : cylens){
        int K = cycnt[a];
        if(a == rt){
            buf[a] = Mi(K).pow(K-2) * Mi(a).pow(K);
        } else {
            Mi B = 0;
            for(int b : cylens) if(b < a && a%b == 0){
                B += b * cycnt[b];
            }
            buf[a] = 0;
            for(int s=1; s<=K; s++){
                buf[a] += B.pow(s) * comb(K-1,s-1) * Mi(K).pow(K-s) * Mi(a).pow(K-s);
            } 
        }
    }
    Mi ans = 1;
    rep(i,N+1) ans *= buf[i];
    cout << ans.val() << "\n";
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    testcase();
    return 0;
}
accuracy: 0.3
time_ms: 20
memory_kb: 8888
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < (int)(n); i ++)
#define rep1(i, n) for(int i = 1; i <= (int)(n); i ++)
#define MP make_pair

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int MOD = 998244353;

int n, p[300005];
bool vis[300005];
int cnt[300005], tt[300005];

int power(int x, int t)
{
	if(t < 0) t += MOD - 1;
	int ret = 1;
	while(t > 0) {
		if(t & 1) ret = 1LL * ret * x % MOD;
		x = 1LL * x * x % MOD;
		t >>= 1;
	}
	return ret;
}

int main()
{
	scanf("%d", &n);
	rep1(i, n) scanf("%d", &p[i]);
	int g = 0;
	rep1(i, n) if(!vis[i]) {
		int cur = i, cc = 0;
		do {
			vis[cur] = true;
			cur = p[cur];
			cc ++;
		} while(cur != i);
		cnt[cc] ++;
		g = __gcd(g, cc);
	}
	if(cnt[g] == 0 || g > 2) {
		printf("0\n");
		return 0;
	}
	int ans = g == 2 ? cnt[g] : 1;
	for(int i = g; i <= n; i ++) if(cnt[i] != 0) {
		for(int j = i * 2; j <= n; j += i) tt[j] = (tt[j] + 1LL * i * cnt[i]) % MOD;
		if(i == g) ans = 1LL * ans * power(cnt[g], cnt[g] - 2) % MOD * power(g, g - 1) % MOD;
		else ans = 1LL * ans * tt[i] % MOD * power((1LL * cnt[i] * i + tt[i]) % MOD, cnt[i] - 1) % MOD;
	}
	printf("%d\n", ans);
	return 0;
}
accuracy: 0.3
time_ms: 20
memory_kb: 6216
final_rank: 14

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


constexpr int MOD = 998244353;

int mod_mul(int a, int b) {
    return int((1LL * a * b) % MOD);
}

int mod_pow(int base, int exp, int result = 1) {
    while (exp) {
        if (exp & 1) result = mod_mul(result, base);
        base = mod_mul(base, base);
        exp >>= 1;
    }
    return result;
}
struct DSU {
    vector<int> parent;

    DSU(int n) : parent(n, -1) {}

    int find(int x) {
        return parent[x] < 0 ? x : parent[x] = find(parent[x]);
    }

    int size(int x) {
        return -parent[find(x)];
    }

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return false;
        if (parent[x] > parent[y]) swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
        return true;
    }
};

void solve() {
    int n;
    cin >> n;

    vector<int> perm(n);
    for (int& x : perm) {
        cin >> x;
        --x;
    }
    DSU dsu(n);
    
    vector<int> cycleCount(n + 1, 0), degreeCount(n + 1, 0);

    for (int i = 0; i < n; ++i) {
        if (!dsu.unite(i, perm[i])) {
            ++cycleCount[dsu.size(i)];
        }
    }

    for (int len = 1; len <= n; ++len) {
        if (cycleCount[len]) {
            for (int j = len + len; j <= n; j += len) {
                degreeCount[j] += cycleCount[len] * len;
            }
        }
    }
    
    int result = 1;
    int start = 1;

    if (cycleCount[1]) {
        if (cycleCount[1] > 1)
            result = mod_pow(cycleCount[1], cycleCount[1] - 2);
        start = 2;
    } else if (cycleCount[2]) {
        result = mod_mul(mod_pow(cycleCount[2], cycleCount[2] - 1),
                         mod_pow(2, cycleCount[2] - 1));
        start = 3;
    } else {
        cout << 0 << '\n';
        return;
    }

    for (int len = start; len <= n; ++len) {
        if (cycleCount[len]) {
            int base = (1LL * degreeCount[len] + 1LL * len * cycleCount[len]) % MOD;
            result = mod_mul(result, mod_pow(base, cycleCount[len] - 1));
            result = mod_mul(result, degreeCount[len]);
        }
    }

    cout << result << '\n';

}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 7836
final_rank: 4

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


constexpr int MOD = 998244353;

int mod_mul(int a, int b) {
    return int((1LL * a * b) % MOD);
}

int mod_pow(int base, int exp, int result = 1) {
    while (exp) {
        if (exp & 1) result = mod_mul(result, base);
        base = mod_mul(base, base);
        exp >>= 1;
    }
    return result;
}

struct DSU {
    vector<int> parent;

    DSU(int n) : parent(n, -1) {}

    int find(int x) {
        return parent[x] < 0 ? x : parent[x] = find(parent[x]);
    }

    int size(int x) {
        return -parent[find(x)];
    }

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return false;
        if (parent[x] > parent[y]) swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
        return true;
    }
};

void solve() {
    int n;
    cin >> n;

    vector<int> perm(n);
    for (int& x : perm) {
        cin >> x;
        --x;
    }

    DSU dsu(n);
    vector<int> cycleCount(n + 1, 0), degreeCount(n + 1, 0);

    for (int i = 0; i < n; ++i) {
        if (!dsu.unite(i, perm[i])) {
            ++cycleCount[dsu.size(i)];
        }
    }

    for (int len = 1; len <= n; ++len) {
        if (cycleCount[len]) {
            for (int j = len + len; j <= n; j += len) {
                degreeCount[j] += cycleCount[len] * len;
            }
        }
    }

    int result = 1;
    int start = 1;

    if (cycleCount[1]) {
        if (cycleCount[1] > 1)
            result = mod_pow(cycleCount[1], cycleCount[1] - 2);
        start = 2;
    } else if (cycleCount[2]) {
        result = mod_mul(mod_pow(cycleCount[2], cycleCount[2] - 1),
                         mod_pow(2, cycleCount[2] - 1));
        start = 3;
    } else {
        cout << 0 << '\n';
        return;
    }

    for (int len = start; len <= n; ++len) {
        if (cycleCount[len]) {
            int base = (1LL * degreeCount[len] + 1LL * len * cycleCount[len]) % MOD;
            result = mod_mul(result, mod_pow(base, cycleCount[len] - 1));
            result = mod_mul(result, degreeCount[len]);
        }
    }

    cout << result << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 7836
final_rank: 4

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

using i64 = long long;

constexpr int MOD = 998244353;

int mod_mul(int a, int b) {
    return int((1LL * a * b) % MOD);
}

int mod_pow(int base, int exp, int result = 1) {
    while (exp) {
        if (exp & 1) result = mod_mul(result, base);
        base = mod_mul(base, base);
        exp >>= 1;
    }
    return result;
}

struct DSU {
    vector<int> parent;

    DSU(int n) : parent(n, -1) {}

    int find(int x) {
        return parent[x] < 0 ? x : parent[x] = find(parent[x]);
    }

    int size(int x) {
        return -parent[find(x)];
    }

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return false;
        if (parent[x] > parent[y]) swap(x, y);
        parent[x] += parent[y];
        parent[y] = x;
        return true;
    }
};

void solve() {
    int n;
    cin >> n;

    vector<int> perm(n);
    for (int& x : perm) {
        cin >> x;
        --x;
    }

    DSU dsu(n);
    vector<int> cycleCount(n + 1, 0), degreeCount(n + 1, 0);

    for (int i = 0; i < n; ++i) {
        if (!dsu.unite(i, perm[i])) {
            ++cycleCount[dsu.size(i)];
        }
    }

    for (int len = 1; len <= n; ++len) {
        if (cycleCount[len]) {
            for (int j = len + len; j <= n; j += len) {
                degreeCount[j] += cycleCount[len] * len;
            }
        }
    }

    int result = 1;
    int start = 1;

    if (cycleCount[1]) {
        if (cycleCount[1] > 1)
            result = mod_pow(cycleCount[1], cycleCount[1] - 2);
        start = 2;
    } else if (cycleCount[2]) {
        result = mod_mul(mod_pow(cycleCount[2], cycleCount[2] - 1),
                         mod_pow(2, cycleCount[2] - 1));
        start = 3;
    } else {
        cout << 0 << '\n';
        return;
    }

    for (int len = start; len <= n; ++len) {
        if (cycleCount[len]) {
            int base = (1LL * degreeCount[len] + 1LL * len * cycleCount[len]) % MOD;
            result = mod_mul(result, mod_pow(base, cycleCount[len] - 1));
            result = mod_mul(result, degreeCount[len]);
        }
    }

    cout << result << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 7836
final_rank: 4

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

using i64 = long long;
using u64 = unsigned long long;

constexpr int MOD = 998244353;

int mul(int x, int y) {
    return int((1LL * x * y) % MOD);
}

int qpw(int a, int b, int r = 1) {
    while (b) {
        if (b & 1) r = mul(r, a);
        a = mul(a, a);
        b >>= 1;
    }
    return r;
}

struct DSU {
    vector<int> par;

    DSU(int n) : par(n, -1) {}

    int find(int x) {
        return par[x] < 0 ? x : par[x] = find(par[x]);
    }

    int size(int x) {
        return -par[find(x)];
    }

    int merge(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return -1;
        if (par[x] < par[y]) {
            par[x] += par[y];
            par[y] = x;
        } else {
            par[y] += par[x];
            par[x] = y;
        }
        return 0;
    }
};

void solve() {
    int N;
    cin >> N;
    vector<int> p(N);
    for (int i = 0; i < N; ++i) {
        cin >> p[i];
        --p[i]; // 0-indexed
    }

    DSU dsu(N);
    vector<int> buc(N + 1), ct(N + 1);

    for (int i = 0; i < N; ++i) {
        if (dsu.merge(i, p[i]) == -1) {
            ++buc[dsu.size(i)];
        }
    }

    for (int i = 1; i <= N; ++i) {
        if (buc[i]) {
            for (int j = i + i; j <= N; j += i) {
                ct[j] += buc[i] * i;
            }
        }
    }

    int ans = 1;
    int bg = -1;

    if (buc[1]) {
        ans = (buc[1] > 1 ? qpw(buc[1], buc[1] - 2) : 1);
        bg = 2;
    } else {
        if (buc[2]) {
            ans = mul(qpw(buc[2], buc[2] - 1), qpw(2, buc[2] - 1));
        } else {
            cout << "0\n";
            return;
        }
        bg = 3;
    }

    for (int i = bg; i <= N; ++i) {
        if (buc[i]) {
            int base = (ct[i] + 1LL * i * buc[i]) % MOD;
            ans = mul(ans, qpw(base, buc[i] - 1));
            ans = mul(ans, ct[i]);
        }
    }

    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 7836
final_rank: 4

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

ll MOD = 998244353;

ll MUL(ll A, ll B) {
    return (A*B) % MOD;
}

void chMUL(ll& A, ll B) {
    A  = MUL(A,B);
}

ll POW(ll A, ll X) {
    if (X == 0) return 1;
    if (X % 2 == 0) {
        ll B = POW(A, X/2);
        return MUL(B,B);
    }
    return MUL(A, POW(A,X-1));
}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N;
    cin >> N;
    vector<int> A(N);
    rep(i,0,N) cin >> A[i], A[i]--;
    vector<int> C(N+1,0);
    vector<bool> B(N, false);
    rep(i,0,N) {
        if (B[i]) continue;
        int Cur = i, cnt = 0;
        while(1) {
            if (B[Cur]) break;
            B[Cur] = true;
            Cur = A[Cur];
            cnt++;
        }
        C[cnt]++;
    }
    vector<int> D(N+1,0);
    rep(i,1,N+1) {
        rep(j,2,N+1) {
            if (i*j > N) break;
            D[i*j] += C[i] * i;
        }
    }
    ll ANS;
    if (C[1] == 0) {
        if (C[2] == 0) {
            cout << 0 << endl;
            return 0;
        }
        ANS = MUL(C[2], (C[2] == 1 ? 1 : MUL(POW(C[2], C[2]-2), POW(2, C[2]-1))));
        rep(i,3,N+1) {
            if (C[i] == 0) continue;
            chMUL(ANS, MUL(D[i], POW(D[i] + C[i] * i, C[i] - 1)));
        }
    }
    else {
        ANS = (C[1] == 1 ? 1 : POW(C[1], C[1]-2));
        rep(i,2,N+1) {
            if (C[i] == 0) continue;
            chMUL(ANS, MUL(D[i], POW(D[i] + C[i] * i, C[i] - 1)));
        }
    }
    cout << ANS << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 6780
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

ll MOD = 998244353;

ll MUL(ll A, ll B) {
    return (A*B) % MOD;
}

void chMUL(ll& A, ll B) {
    A  = MUL(A,B);
}

ll POW(ll A, ll X) {
    if (X == 0) return 1;
    if (X % 2 == 0) {
        ll B = POW(A, X/2);
        return MUL(B,B);
    }
    return MUL(A, POW(A,X-1));
}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N;
    cin >> N;
    vector<int> A(N);
    rep(i,0,N) cin >> A[i], A[i]--;
    vector<int> C(N+1,0);
    vector<bool> B(N, false);
    rep(i,0,N) {
        if (B[i]) continue;
        int Cur = i, cnt = 0;
        while(1) {
            if (B[Cur]) break;
            B[Cur] = true;
            Cur = A[Cur];
            cnt++;
        }
        C[cnt]++;
    }
    vector<int> D(N+1,0);
    rep(i,1,N+1) {
        rep(j,2,N+1) {
            if (i*j > N) break;
            D[i*j] += C[i] * i;
        }
    }
    ll ANS;
    if (C[1] == 0) {
        if (C[2] == 0) {
            cout << 0 << endl;
            return 0;
        }
        ANS = C[2] * (C[2] == 1 ? 1 : MUL(POW(C[2], C[2]-2), POW(2, C[2]-1)));
        rep(i,3,N+1) {
            if (C[i] == 0) continue;
            chMUL(ANS, MUL(D[i], POW(D[i] + C[i] * i, C[i] - 1)));
        }
    }
    else {
        ANS = (C[1] == 1 ? 1 : POW(C[1], C[1]-2));
        rep(i,2,N+1) {
            if (C[i] == 0) continue;
            chMUL(ANS, MUL(D[i], POW(D[i] + C[i] * i, C[i] - 1)));
        }
    }
    cout << ANS << endl;
}
accuracy: 0.3
time_ms: 20
memory_kb: 6612
final_rank: 15

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

int read() {
  int x(0), c(getchar());
  while (c < '0' || c > '9') c = getchar();
  while (c >= '0' && c <= '9') x = x * 10 + (c - '0'), c = getchar();
  return x;
}
void write(int x) {
  static char buf[14];
  if (!x) {
    putchar('0');
    return;
  }
  int d(0);
  while (x) buf[d++] = x % 10 + '0', x /= 10;
  while (d) putchar(buf[--d]);
}

const int MXN = 300005;
const int DVS = 998244353;
int N, prm[MXN], ans, cnt[MXN], coe[MXN];
bool vis[MXN];

int main() {
    N = read();
    for (int i(0); i != N; ++i) prm[i] = read() - 1;
    for (int i(0); i <= N; ++i) vis[i] = 0, cnt[i] = 0, coe[i] = 0;
    for (int i(0); i != N; ++i) {
      if (!vis[i]) {
        int j(i), len(0);
        while (!vis[j]) {
          vis[j] = true;
          ++len;
          j = prm[j];
        }
        ++cnt[len];
      }
    }
    for (int i(1); i <= N; ++i)
      for (int j(i + i); j <= N; j += i) coe[j] += i * cnt[i];
    ans = 1;
    for (int i(3); i <= N; ++i) {
      if (!cnt[i]) continue;
      int bas((coe[i] + cnt[i] * 1LL * i) % DVS);
      ans = ans * 1LL * coe[i] % DVS;
      for (int j(0); j != cnt[i] - 1; ++j) ans = ans * 1LL * bas % DVS;
    }
    int c1(cnt[1]), c2(cnt[2]);
    int n(c1 + c2 * 2);
    if (!c1 && !c2) {
      ans = 0;
    } else if (!c1) {
      for (int i(0); i != c2 - 1; ++i) ans = ans * 1LL * n % DVS;
    } else if (!c2) {
      if (c1 > 1)
        for (int i(0); i != n - 2; ++i) ans = ans * 1LL * n % DVS;
    } else {
      for (int i(0); i != c1 - 1; ++i) ans = ans * 1LL * c1 % DVS;
      for (int i(0); i != c2 - 1; ++i) ans = ans * 1LL * n % DVS;
    }
    write(ans), putchar('\n');
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 7240
final_rank: 1

code_snippet: // Problem: A - Invariant Tree
// Contest: Virtual Judge - 20240214补题
// URL: https://vjudge.net/contest/609963#problem/A
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define rep1(i, l, r) for (int i = l; i <= int(r); ++i)
#define rep2(i, l, r) for (int i = l; i >= int(r); --i)
#define cop(i, l, r, a, b) rep1(i, l, r) a[i] = b[i]
#define rep(i, x) for (int i = pnt[x]; i; i = nxt[i])
#define rer(i, l, r, a) rep1(i, l, r) read(a[i])
#define ptc putchar
#define il inline
#define eb emplace_back
#define ef emplace_front
#define mp make_pair
#define fst first
#define snd second
#define sqr(x) ((x) * (x))
#define ls(x) x << 1
#define rs(x) x << 1 | 1
#define rout return 0
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 bll;
// typedef unsigned __int128 ubll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int MAXN = 3e5 + 10, inf = ~0U >> 2, INF = ~0U >> 1;
const int LOGN = log2(MAXN) + 1;
const int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
namespace stupid_lrc {
	template <typename T> il bool read(T &x) {
		x = 0; bool f = false; char ch;
		while (!isdigit(ch = getchar())) {
			f ^= !(ch ^ '-');
			if (ch == EOF) return false;
		}
		while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch & 15), ch = getchar();
		if (f) x = ~x + 1; return true;
	}
	il int read() {int x; read(x); return x;}

	template <typename T> il bool read(pair <T, T> &x) {return read(x.fst) && read(x.snd);}
	
	template <typename T> il void gmin(T &x, T y) {x = x < y ? x : y;}
	
	template <typename T> il void gmax(T &x, T y) {x = x > y ? x : y;}

	template <typename T, typename ...L>
	il bool read(T &x, L &...y) {return read(x) && read(y...);}

	template <typename T> il T lowbit(const T &x) {return x & -x;}
}
using namespace stupid_lrc;
int n, s, cnt[MAXN], vis[MAXN];
vector <int> val, lnk[MAXN];
const int mod = 998244353;
ll fac[MAXN], inv[MAXN], ans = 1;

il ll qpow(ll a, int b) {
	if (!~b) return 1;
	ll ans = 1;
	while (b) {
		if (b & 1) (ans *= a) %= mod;
		(a *= a) %= mod; b >>= 1;
	} return ans;
}

il void dfs(int x) {
	if (vis[x]) return;
	vis[x] = 1; ++s;
	for (auto v : lnk[x]) dfs(v);
}

il ll C(int n, int m) {
	if (n < m) return 0;
	return fac[n] * inv[n - m] % mod * inv[m] % mod;
}

int main() {
	read(n); fac[0] = 1;
	if (n == 1) return puts("1"), 0;
	rep1(i, 1, n) lnk[i].eb(read()), fac[i] = fac[i - 1] * i % mod;
	rep1(i, 1, n) if (!vis[i]) {
		s = 0; dfs(i);
		if (!cnt[s]++) val.eb(s);
	} sort(val.begin(), val.end(), greater <int>()); inv[n] = qpow(fac[n], mod - 2);
	if (cnt[1] == n) return printf("%lld\n", qpow(n, n - 2)), 0;
	rep2(i, n - 1, 0) inv[i] = inv[i + 1] * (i + 1) % mod;
	if (!cnt[1] && !cnt[2]) return puts("0"), 0;
	for (auto v : val) {
		if (v == 1) {
			(ans *= qpow(cnt[1], cnt[1] - 2)) %= mod;
			continue;
		}
		if (v == 2 && !cnt[1]) {
			(ans *= qpow(cnt[2], cnt[2] - 2) * cnt[2] % mod * qpow(2, cnt[2] - 1)) %= mod;
			continue;
		}
		ll now = 0, pre = 0;
		for (auto w : val) {
			if (w >= v) continue;
			if (v % w == 0) (pre += 1ll * cnt[w] * w) %= mod;
		}
		rep1(k, 1, cnt[v]) {
			(now += (k == cnt[v] ? 1 : k * qpow(cnt[v], cnt[v] - 1 - k) % mod * C(cnt[v], k) % mod) * qpow(pre, k) % mod * qpow(v, cnt[v] - k)) %= mod;
		} (ans *= now) %= mod;
	} printf("%lld\n", ans);
	rout;
}
accuracy: 1
time_ms: 40
memory_kb: 34568
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define INF 1000000000
#define LINF 1000000000000000000
#define mod 998244353
#define F first
#define S second
#define ll long long
#define N 300010
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
using namespace std;
char buf[1<<23],*p1=buf,*p2=buf;
ll rint(){
	ll ret=0;
	char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c-'0'),c=getchar();
	return ret;
}
ll fact[N],inv_fac[N];
ll ksm(ll x,ll y)
{
	ll ret=1;
	while(y>0)
	{
		if(y&1)
		{
			ret=(ret*x)%mod;
		}
		x=(x*x)%mod;
		y>>=1;
	}
	return ret;
}
ll C(ll x,ll y){return (x<y||x<0||y<0)?0:(fact[x]*((inv_fac[y]*inv_fac[x-y])%mod))%mod;}
ll n,a[N],cycnum[N],hvnum[N],pw[N];
bool vis[N];
int main(){
	ll i,j;
	fact[0]=1;
	for(i=1;i<N;i++)
	{
		fact[i]=(fact[i-1]*i)%mod;
	}
	inv_fac[N-1]=ksm(fact[N-1],mod-2);
	for(i=N-2;i>=0;i--)
	{
		inv_fac[i]=(inv_fac[i+1]*(i+1))%mod;
	}
	n=rint();
	for(i=0;i<n;i++)
	{
		a[i]=rint()-1;
	}
	for(i=0;i<n;i++)
	{
		if(!vis[i])
		{
			ll cnt=0;
			for(j=i;!vis[j];j=a[j])
			{
				cnt++;
				vis[j]=true;
			}
			cycnum[cnt]++;
		}
	}
	ll ans=1;
	if(cycnum[1]>1)
	{
		ans=(ans*ksm(cycnum[1],cycnum[1]-2))%mod;
	}
	for(i=1;i<=n;i++)
	{
		if(!cycnum[i])
		{
			continue;
		}
		for(j=i+i;j<=n;j+=i)
		{
			hvnum[j]+=cycnum[i]*i;
		}
	}
	for(i=2;i<=n;i++)
	{
		ll num=cycnum[i];
		if(!num)
		{
			continue;
		}
		ll tot=hvnum[i];
		if(!tot)
		{
			if(i>2)
			{
				puts("0");
				return 0;
			}
			ans=ksm(num*2,num-1);
			continue;
		}
		pw[0]=1;
		for(j=1;j<=num;j++)
		{
			pw[j]=(pw[j-1]*num*i)%mod;
		}
		ll sum=0,curpw=1;
		for(j=1;j<=num;j++)
		{
			curpw=(curpw*tot)%mod;
			sum=(sum+((C(num-1,j-1)*pw[num-j])%mod)*curpw)%mod;
		}
		ans=(ans*sum)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 19084
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n,p[1000003];
bool vis[1000003]; 
int cnt[1000003],f[1000003];
int mypow(int x,int times){
	if(x==1)return 1;
	int ret=1;
	while(times){
		if(times&1)
			ret=1ll*ret*x%mod;
		times>>=1;
		x=1ll*x*x%mod;
	}return ret;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>p[i],p[i]--;
	for(int i=0;i<n;i++)
		if(!vis[i]){
			int w=0,j=i;
			while(!vis[j])
				w++,vis[j]=1,j=p[j];
			cnt[w]++;
		}
	vector<int>v;
	for(int i=1;i<=n;i++)
		if(cnt[i])
			v.push_back(i);
	for(auto i:v)
		for(auto j:v)
			if(j>i&&j%i==0)
				f[j]+=cnt[i]*i;
	int ans=1;
	for(int i=n;i>0;i--)
		if(cnt[i])
			if(i>2||i==2&&cnt[1])
				ans=1ll*ans*f[i]%mod*mypow(f[i]+cnt[i]*i,cnt[i]-1)%mod;
			else
				if(i==2)
					ans=1ll*ans*mypow(cnt[i]*i,cnt[i]-1)%mod;
				else
					ans=1ll*ans*mypow(cnt[i]*i,cnt[i]-2)%mod;
	cout<<ans<<'\n';
}
accuracy: 1
time_ms: 20
memory_kb: 11680
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n,p[1000003];
bool vis[1000003]; 
int cnt[1000003],f[1000003];
int mypow(int x,int times){
	if(x==1)return 1;
	int ret=1;
	while(times){
		if(times&1)
			ret=1ll*ret*x%mod;
		times>>=1;
		x=1ll*x*x%mod;
	}return ret;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>p[i],p[i]--;
	for(int i=0;i<n;i++)
		if(!vis[i]){
			int w=0,j=i;
			while(!vis[j])
				w++,vis[j]=1,j=p[j];
			cnt[w]++;
		}
	vector<int>v;
	for(int i=1;i<=n;i++)
		if(cnt[i])
			v.push_back(i);
	for(auto i:v)
		for(auto j:v)
			if(j>i&&j%i==0)
				f[j]+=cnt[i];
	int ans=1;
	for(int i=n;i>0;i--)
		if(cnt[i])
			if(i>2||i==2&&cnt[1])
				ans=1ll*ans*f[i]%mod*mypow(f[i]+cnt[i]*i,cnt[i]-1)%mod;
			else
				if(i==2)
					ans=1ll*ans*mypow(cnt[i]*i,cnt[i]-1)%mod;
				else
					ans=1ll*ans*mypow(cnt[i]*i,cnt[i]-2)%mod;
	cout<<ans<<'\n';
}
accuracy: 0.06666666666666667
time_ms: 10
memory_kb: 11576
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define N 300005
#define mod 998244353
#define ll long long
vector<int>v[N];
int n,s,ans,a[N],vis[N],cnt[N];
int qpow(int n,int m){
	int s=n,ans=1;
	while (m){
		if (m&1)ans=(ll)ans*s%mod;
		s=(ll)s*s%mod;
		m>>=1;
	}
	return ans;
}
void dfs(int k){
	if (vis[k])return;
	s++,vis[k]=1,dfs(a[k]);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		if (!vis[i])s=0,dfs(i),cnt[s]++;
	ans=1; 
	for(int i=1;i<=n;i++)
		for(int j=(i<<1);j<=n;j+=i)v[j].push_back(i);
	if ((!cnt[1])&&(!cnt[2])){
		printf("0\n");
		return 0;
	}
	int st=2;
	if (cnt[1]){
		if (cnt[1]!=1)ans=qpow(cnt[1],cnt[1]-2);
	}
	else{
		st=3;
		ans=(ll)qpow(cnt[2],cnt[2]-1)*qpow(2,cnt[2]-1)%mod;
	}
	for(int i=st;i<=n;i++){
		if (!cnt[i])continue;
		int w=0,s=0;
		for(int j=0;j<v[i].size();j++)w+=v[i][j]*cnt[v[i][j]];
		ans=(ll)ans*w*qpow(w+i*cnt[i],cnt[i]-1)%mod;
	}
	printf("%d\n",ans);
	return 0;
}
accuracy: 0.7
time_ms: 140
memory_kb: 38536
final_rank: 13

code_snippet: #include <bits/stdc++.h>
const int mod=998244353;
using namespace std;
int n,nxt[300010],fac[300010],invfac[300010],f[300010],cnt[300010];
bool vis[300010];
int ksm(int a,int k){
	int res=1;
	for(;k;k>>=1,a=1ll*a*a%mod) if(k&1) res=1ll*res*a%mod;
	return res;
}
int C(int n,int m){
	if(n<m||m<0) return 0;
	return 1ll*fac[n]*invfac[m]%mod*invfac[n-m]%mod;
}
int calc(int n,int k){//n vertices into k trees
	return 1ll*C(n-1,k-1)*ksm(n,n-k)%mod;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&nxt[i]);
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=1ll*i*fac[i-1]%mod;
	invfac[n]=ksm(fac[n],mod-2);
	for(int i=n-1;i>=0;i--) invfac[i]=(i+1ll)*invfac[i+1]%mod;
	for(int i=1;i<=n;i++){
		if(vis[i]) continue;
		int u=i,tot=0;
		while(!vis[u]){
			tot++;
			vis[u]=true;
			u=nxt[u];
		}
		cnt[tot]++;
	}
	int ans=cnt[1]?1ll*calc(cnt[1],1)*ksm(cnt[1],mod-2)%mod:(cnt[2]?1ll*ksm(2,cnt[2]-1)*calc(cnt[2],1)%mod:0),st=cnt[1]?2:3;
	for(int i=1;i<=st;i++){
		for(int j=2*i;j<=n;j+=i) f[j]=(f[j]+1ll*i*cnt[i])%mod;
	}
	for(int i=st;i<=n;i++){
		if(!cnt[i]) continue;
		int res=0;
		for(int j=1;j<=cnt[i];j++){
			res=(res+1ll*ksm(i,cnt[i]-j)*ksm(f[i],j)%mod*calc(cnt[i],j))%mod;
		}
		ans=1ll*res*ans%mod;
		for(int j=2*i;j<=n;j+=i) f[j]=(f[j]+1ll*i*cnt[i])%mod;
	}
	printf("%d\n",ans);
}
accuracy: 0.1111111111111111
time_ms: 20
memory_kb: 7964
final_rank: 18