#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
typedef unsigned long long ULL;
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn=600;
int n,rt1,rt2,a,size1[maxn],size2[maxn],dp[maxn][maxn];
vector <int> G1[maxn],G2[maxn];
int prime[maxn],len;
ULL H1[maxn],H2[maxn];
struct ZKW {
int n,m,s,t,cost,ans;
int d[maxn<<1],vis[maxn<<1],first[maxn<<1],inq[maxn<<1],next[510*510*2];
struct Edge {int from,to,flow,cost;}edges[510*510*2];
void init(int n) {
this->n=n;m=0;
memset(first,-1,sizeof(first));
memset(inq,0,sizeof(inq));
}
void AddEdge(int from,int to,int cap,int cost) {
edges[m]=(Edge){from,to,cap,cost};next[m]=first[from];first[from]=m++;
edges[m]=(Edge){to,from,0,-cost};next[m]=first[to];first[to]=m++;
}
int BFS() {
for(int i=1;i<=n;i++) d[i]=maxn;
queue<int> Q;Q.push(t);d[t]=0;
while(!Q.empty()) {
int x=Q.front();Q.pop();inq[x]=0;
for(int i=first[x];i!=-1;i=next[i]) {
Edge& e=edges[i^1];
if(e.flow&&d[e.from]>d[x]+e.cost) {
d[e.from]=d[x]+e.cost;
if(!inq[e.from]) inq[e.from]=1,Q.push(e.from);
}
}
}
for(int i=0;i<=m;i++) edges[i].cost+=d[edges[i].to]-d[edges[i].from];
cost+=d[s];return d[s]!=maxn;
}
int DFS(int x,int a) {
if(x==t||!a) {ans+=cost*a;return a;}
int flow=0,f;vis[x]=1;
for(int i=first[x];i!=-1;i=next[i]) {
Edge& e=edges[i];
if(e.flow&&!e.cost&&!vis[e.to]&&(f=DFS(e.to,min(e.flow,a)))) {
e.flow-=f;edges[i^1].flow+=f;
a-=f;flow+=f;if(!a) break;
}
}
return flow;
}
int solve(int s,int t) {
this->s=s;this->t=t;ans=cost=0;
while(BFS()) do memset(vis,0,sizeof(vis));while(DFS(s,maxn));
return ans;
}
}sol;
bool vis[10010];
void init(int x)
{
for(int i=2;i<=x;i++)
{
if(!vis[i])prime[++len]=i;
for(int j=1;j<=len && i*prime[j]<=x;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
void dfs1(int now)
{
H1[now]=size1[now]=1;
for(int v:G1[now])
{
dfs1(v);
H1[now]+=H1[v]*(ULL)prime[size1[v]];
size1[now]+=size1[v];
}
}
void dfs2(int now)
{
H2[now]=size2[now]=1;
for(int v:G2[now])
{
dfs2(v);
H2[now]+=H2[v]*(ULL)prime[size2[v]];
size2[now]+=size2[v];
}
}
void DP(int x,int y)
{
dp[x][y]=maxn;
if(H1[x]!=H2[y] || size1[x]!=size2[y])return;
if(size1[x]==1 && size2[y]==1)
{
dp[x][y]=(x!=y);
return;
}
for(int v1:G1[x])
for(int v2:G2[y])DP(v1,v2);
int N=2+G1[x].size()+G2[y].size(),s=1,t=N;
sol.init(N);
for(int i=0;i<G1[x].size();i++)sol.AddEdge(s,i+2,1,0);
for(int i=0;i<G1[x].size();i++)
for(int j=0;j<G2[y].size();j++)
{
int v1=G1[x][i],v2=G2[y][j];
if(H1[v1]==H2[v2] && size1[v1]==size2[v2])sol.AddEdge(i+2,j+2+G1[x].size(),1,dp[v1][v2]);
}
for(int i=0;i<G2[y].size();i++)sol.AddEdge(i+2+G1[x].size(),t,1,0);
int ans=sol.solve(s,t);
dp[x][y]=ans+(x!=y);
}
int main()
{
init(4000);
n=read();
for(int i=1;i<=n;i++)
{
a=read();
if(a==0)rt1=i;
else G1[a].push_back(i);
}
dfs1(rt1);
for(int i=1;i<=n;i++)
{
a=read();
if(a==0)rt2=i;
else G2[a].push_back(i);
}
dfs2(rt2);
DP(rt1,rt2);
printf("%d\n",dp[rt1][rt2]);
return 0;
}