Problem Summary
You have cards. Each card has two sides — the front shows a number and the back shows . Both sequences and are permutations of . Count the number of subsets of cards such that every number from to appears on at least one chosen card. Output the answer modulo .
Approach
Build a graph by connecting the two numbers on each card. Since and are permutations, every value appears exactly twice, so every vertex has degree and the resulting graph is a disjoint union of cycles.
Consider a simpler sub-problem first: on a chain of numbers , count the ways to pick a subset such that for every pair of adjacent numbers at least one is chosen. Splitting by whether is picked, let denote the answer. We have , , and — Fibonacci-like.
Now the real sub-problem: on a cycle of numbers, count the subsets where for every vertex at least one of its two incident edges is chosen. Let denote the answer. Casework on whether the edge is picked gives , , and . A quick check reveals , the -th Lucas number.
Multiply across every cycle in the graph to get the final answer.
Code
#include<bits/stdc++.h>using namespace std;long long a[200005];long long mod=998244353;int p[200005];int q[200005];int fa[200005];int siz[200005];int vis[200005];int findd(int x){ return fa[x]==x?x:(fa[x]=findd(fa[x]));}int main(){ int n; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&p[i]); for(int i=1;i<=n;i++)scanf("%d",&q[i]); for(int i=1;i<=n;i++){fa[i]=i;siz[i]=1;} for(int i=1;i<=n;i++)if(findd(p[i])!=findd(q[i])) { siz[findd(q[i])]+=siz[findd(p[i])]; fa[findd(p[i])]=findd(q[i]); } a[0]=2; a[1]=1; for(int i=2;i<=n;i++)a[i]=(a[i-1]+a[i-2])%mod; long long ans=1; for(int i=1;i<=n;i++)if(!vis[findd(i)]) { ans=ans*a[siz[findd(i)]]%mod; vis[findd(i)]=1; } printf("%lld\n",ans); return 0;}