#include "bits/stdc++.h" using namespace std; typedef long long ll; typedef pair pii; typedef pair pll; const int INF = 1e9; const ll LINF = 1e18; template ostream& operator << (ostream& out,const pair& o){ out << "(" << o.first << "," << o.second << ")"; return out; } template ostream& operator << (ostream& out,const vector V){ for(int i = 0; i < V.size(); i++){ out << V[i]; if(i!=V.size()-1) out << " ";} return out; } template ostream& operator << (ostream& out,const vector > Mat){ for(int i = 0; i < Mat.size(); i++) { if(i != 0) out << endl; out << Mat[i];} return out; } template ostream& operator << (ostream& out,const map mp){ out << "{ "; for(auto it = mp.begin(); it != mp.end(); it++){ out << it->first << ":" << it->second; if(mp.size()-1 != distance(mp.begin(),it)) out << ", "; } out << " }"; return out; } /* 問題文============================================================ 貯金箱くんはとても退屈していました。 そこで自分が持っている硬貨で遊ぶことにしました。 まず自分の持っている硬貨を床にばらまき、そこから N 枚硬貨を選び円形に並べます。 次に N 枚の硬貨から適当に1枚選びます。 選んだ硬貨の額面を D 円としたとき、選んだ硬貨から時計回りに D 個先の硬貨と、反時計回りに D 個先の硬貨をひっくり返します。 ただし時計回りでも反時計回りでも同じ硬貨だった場合はその硬貨を1回だけひっくり返します。 貯金箱くんは、この操作を繰り返しすべての硬貨を表向きにしたいです。 硬貨の並び、額面、最初の裏表が与えられるのですべての硬貨を表向きにできるか判定してください。 ただし同じ硬貨を複数回選んでもよいとします。 ================================================================= 解説============================================================= ================================================================ */ ll V; vector> G; vector match; vector used; void add_edge(ll u, ll v) { G[u].push_back(v); // G[v].push_back(u); } bool dfs(ll v) { used[v] = 1; for (int i = 0; i < G[v].size(); i++) { ll u = G[v][i], w = match[u]; if (w < 0 || ((used[w] == 0) && dfs(w))) { match[v] = u; match[u] = v; return true; } } return false; } ll bipartite_matching() { ll res = 0; for (int i = 0; i < (int)match.size();i++)match[i] = -1; for (int v = 0;v < V;v++) { if (match[v] < 0) { for (int i = 0; i < (int)used.size();i++)used[i] = 0; if (dfs(v))res++; } } return res; } void dfs(ll n,vector& check,vector>&G){ if(check[n] == 1) return; check[n] = 1; for(auto next:G[n]){ dfs(next,check,G); } } string solve(){ ll N; cin >> N; vector D(N); for(auto& in:D) cin >> in; vector W(N); for(auto& in:W) cin >> in; vector> Graph(N); vector roots; for(int i = 0; i < N;i++){ if((i+D[i])%N == (i-D[i]+10000*N)%N){ roots.push_back((i+D[i])%N); } else{ Graph[(i+D[i])%N].push_back((i-D[i]+10000*N)%N); Graph[(i-D[i]+10000*N)%N].push_back((i+D[i])%N); } } cout << roots << endl; for(auto root:roots){ vector check(N); dfs(root,check,Graph); for(int i = 0; i < N;i++){ W[i] |= check[i]; } } V = N; G.resize(N); match.resize(N); used.resize(N); ll cnt = 0; for(int i = 0; i < N;i++){ if(W[i] == 1) continue; cnt++; for(auto j:Graph[i]){ if(W[j] == 0){ add_edge(i,j); } } } if(cnt&1) return "No"; if(bipartite_matching() == cnt/2) return "Yes"; return "No"; } int main(void) { cin.tie(0); ios_base::sync_with_stdio(false); cout << solve() << endl; return 0; }