Consider count enumeration species substitution, determined fixed point number in each permutation
First consider a weakened version of the title, is no label-free number to the map
Replacement of the role we have to point to the edge
The replacement of painted many rings, find an edge in either a replacement or a different permutation
In a fixed point number and substitution in different permutations respectively seek
The number of points within a fixed permutation is , Consider if there are side , then there must be edge And so on, and considering and It is the equivalent of
In different permutations, considering the size of two replacement , then one side will come out edges, thus actually fixed point number
These equivalence classes may occur can not occur, the contribution of the answer is
Found only related to the size and displacement, violence enumeration split, count the number of programs each split
A number of solutions prior arrangement , the contribution of a loop is Disorder between cycles of the same size, there is a Contributions
Consider this a stronger restriction Euler
I.e., the degree of each point is an even number
Also considered a substitution within the side
where the length is odd
, all the displaced are on the point of impact does not appear even number, you can regardless of
if the length is even
, wherein
not a fixed point on the parity is not affected, and the last to take all diagonal points fixed point causes all degrees + 1
Consider edge between a replacement
for a
influence the degree that point
,Correct
influence is
We now find that the contribution can first take on will not be affected
Then you can have In the first method of the i-th degree of substitution of all + 1, The method Replacement of all degree + 1
Then the number of such programs is the desire to meet the limits, can be exclusive or matrix Gaussian elimination, the number of contributions to the final element consisting of
But there are even better properties
We now Communication block form, just find a spanning tree, the spanning tree outer side pick, pick points other than the root
Found root side of the tree and corresponds to the only viable solution
Points to , selected number of points number selected side is , a communication block
Program number is
With disjoint-set to maintain
The main demand is the fixed point number, consider a fixed point or displacement between the displacement, violence enumerate the number of split multiplier scheme
quickly calculated the number of feasible solution by constructing a spanning tree, very clever
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans; }
void Add(int &a, int b){ a = add(a, b); }
cs int N = 55;
int gcd(int a, int b){ return !b ? a : gcd(b, a % b); }
int n, ans, inv[N], g[N][N];
int fa[N], sm[N];
int find(int x){ return x == fa[x] ? x : fa[x] = find(fa[x]); }
int loop[N], ct[N], now;
int calc(){
int res = 0;
for(int i = 1; i <= now; i++) fa[i] = i, sm[i] = 0;
for(int i = 1; i <= now; i++){
int v = loop[i]; res += ((v - 1) >> 1);
if(!(v&1)) sm[i] = 1;
}
for(int i = 1; i <= now; i++){
for(int j = i+1; j <= now; j++){
int u = loop[i], v = loop[j], gc = g[u][v];
int a = (u/gc) & 1, b = (v/gc) & 1;
if(a && b) fa[find(i)] = find(j), res += gc;
if(a && !b) sm[j] += gc;
if(!a && b) sm[i] += gc;
if(!a && !b) res += gc;
}
}
for(int i = 1; i <= now; i++)
if(find(i) == i){
++res; res += sm[i] == 0 ? 0 : sm[i] - 1;
} else sm[find(i)] += sm[i];
res -= now; return ksm(2, res);
}
void dfs(int las, int rest, int coef){
if(!rest){ Add(ans, mul(coef, calc())); return; }
for(int i = min(las, rest); i; i--){
++ct[i]; loop[++now] = i;
dfs(i, rest - i, mul(coef, mul(inv[i], inv[ct[i]])));
--ct[i]; --now;
}
}
int main(){
cin >> n; inv[0] = inv[1] = 1;
for(int i = 2; i <= n; i++) inv[i] = mul(Mod-Mod/i, inv[Mod%i]);
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) g[i][j] = gcd(i, j);
dfs(n, n, 1);
cout << ans; return 0;
}