#![allow(unused_imports)]
#![allow(non_snake_case, unused)]

use std::cmp::*;
use std::collections::*;
use std::ops::*;

macro_rules! eprint {
	($($t:tt)*) => {{
		use ::std::io::Write;
		let _ = write!(::std::io::stderr(), $($t)*);
	}};
}
macro_rules! eprintln {
	() => { eprintln!(""); };
	($($t:tt)*) => {{
		use ::std::io::Write;
		let _ = writeln!(::std::io::stderr(), $($t)*);
	}};
}
macro_rules! dbg {
	($v:expr) => {{
		let val = $v;
		eprintln!("[{}:{}] {} = {:?}", file!(), line!(), stringify!($v), val);
		val
	}}
}

macro_rules! mat {
	($($e:expr),*) => { Vec::from(vec![$($e),*]) };
	($($e:expr,)*) => { Vec::from(vec![$($e),*]) };
	($e:expr; $d:expr) => { Vec::from(vec![$e; $d]) };
	($e:expr; $d:expr $(; $ds:expr)+) => { Vec::from(vec![mat![$e $(; $ds)*]; $d]) };
}

macro_rules! ok {
	($a:ident$([$i:expr])*.$f:ident()$(@$t:ident)*) => {
		$a$([$i])*.$f($($t),*)
	};
	($a:ident$([$i:expr])*.$f:ident($e:expr$(,$es:expr)*)$(@$t:ident)*) => { {
		let t = $e;
		ok!($a$([$i])*.$f($($es),*)$(@$t)*@t)
	} };
}

pub fn readln() -> String {
	let mut line = String::new();
	::std::io::stdin().read_line(&mut line).unwrap_or_else(|e| panic!("{}", e));
	line
}

macro_rules! read {
	($($t:tt),*; $n:expr) => {{
		let stdin = ::std::io::stdin();
		let ret = ::std::io::BufRead::lines(stdin.lock()).take($n).map(|line| {
			let line = line.unwrap();
			let mut it = line.split_whitespace();
			_read!(it; $($t),*)
		}).collect::<Vec<_>>();
		ret
	}};
	($($t:tt),*) => {{
		let line = readln();
		let mut it = line.split_whitespace();
		_read!(it; $($t),*)
	}};
}

macro_rules! _read {
	($it:ident; [char]) => {
		_read!($it; String).chars().collect::<Vec<_>>()
	};
	($it:ident; [u8]) => {
		Vec::from(_read!($it; String).into_bytes())
	};
	($it:ident; usize1) => {
		$it.next().unwrap_or_else(|| panic!("input mismatch")).parse::<usize>().unwrap_or_else(|e| panic!("{}", e)) - 1
	};
	($it:ident; [usize1]) => {
		$it.map(|s| s.parse::<usize>().unwrap_or_else(|e| panic!("{}", e)) - 1).collect::<Vec<_>>()
	};
	($it:ident; [$t:ty]) => {
		$it.map(|s| s.parse::<$t>().unwrap_or_else(|e| panic!("{}", e))).collect::<Vec<_>>()
	};
	($it:ident; $t:ty) => {
		$it.next().unwrap_or_else(|| panic!("input mismatch")).parse::<$t>().unwrap_or_else(|e| panic!("{}", e))
	};
	($it:ident; $($t:tt),+) => {
		($(_read!($it; $t)),*)
	};
}

pub fn main() {
	let _ = ::std::thread::Builder::new().name("run".to_string()).stack_size(32 * 1024 * 1024).spawn(run).unwrap().join();
}

const MOD: u32 = 1_000_000_007;
const INF: usize = std::usize::MAX/2;

pub trait SetMinMax {
	fn setmin(&mut self, v: Self) -> bool;
	fn setmax(&mut self, v: Self) -> bool;
}
impl<T> SetMinMax for T where T: PartialOrd {
	fn setmin(&mut self, v: T) -> bool {
		*self > v && { *self = v; true }
	}
	fn setmax(&mut self, v: T) -> bool {
		*self < v && { *self = v; true }
	}
}

use std::cmp;
use std::marker::PhantomData;

pub trait Monoid<T> {
    fn id() -> Option<T> {
        None
    }
    // TxT->T
    fn tt_op(l: &Option<T>, r: &Option<T>) -> Option<T>;
    // ExE->E
    fn ee_op(l: &Option<T>, r: &Option<T>) -> Option<T>;
    // TxE->E
    fn te_op(l: &Option<T>, r: &Option<T>) -> Option<T>;
}

pub struct SegOp<T: Ord> {
    phantom: PhantomData<T>,
}

impl<T: Ord + Clone + Add<Output=T>> Monoid<T> for SegOp<T> {
    #[inline]
    // max
    fn tt_op(l: &Option<T>, r: &Option<T>) -> Option<T> {
        match (l.clone(), r.clone()) {
            (Some(l), Some(r)) => Some(max(l,r)),
            (Some(l), None) => Some(l),
            (None, Some(r)) => Some(r),
            (None, None) => None,
        }
    }
    // overwrite
    fn ee_op(l: &Option<T>, r: &Option<T>) -> Option<T> {
        match (l.clone(), r.clone()) {
            (Some(l), Some(r)) => Some(r),
            (Some(l), None) => None,
            (None, Some(r)) => Some(r),
            (None, None) => None,
        }
    }
    // overwrite
    fn te_op(l: &Option<T>, r: &Option<T>) -> Option<T> {
        match (l.clone(), r.clone()) {
            (Some(l), Some(r)) => Some(r),
            (Some(l), None) => None,
            (None, Some(r)) => Some(r),
            (None, None) => None,
        }
    }
}

pub struct SegmentTree<M: Monoid<T>, T: Clone> {
    phantom: PhantomData<M>,
    data: Vec<Option<T>>,
    lazy_data: Vec<Option<T>>,
    size: usize,
    size_p2: usize,
}

impl<M: Monoid<T>, T: Clone> SegmentTree<M, T> {
    pub fn from_vec(v: Vec<T>) -> SegmentTree<M, T> {
        let size = v.len();
        let mut size_p2 = 1;
        while size_p2 < v.len() {
            size_p2 *= 2;
        }
        let mut data = vec![None; size_p2 * 2];
        for (i, x) in v.into_iter().enumerate() {
            data[size_p2 + i] = Some(x);
        }
        for i in (0..size_p2).rev() {
            data[i] = M::tt_op(&data[i * 2 + 0], &data[i * 2 + 1]);
        }
        let mut lazy_data = vec![None; size_p2 * 2];
        SegmentTree {
            phantom: PhantomData,
            data: data,
            lazy_data: lazy_data,
            size: size,
            size_p2: size_p2,
        }
    }

    pub fn size(&self) -> usize {
        self.size
    }

    pub fn eval(&mut self, l: usize, r: usize, k: usize){
        if self.lazy_data[k].is_some() {
            self.data[k] = M::te_op(&self.data[k], &self.lazy_data[k]);
            if r-l>1 {
                self.lazy_data[2*k+0] = M::ee_op(&self.data[2*k+0], &self.lazy_data[k]);
                self.lazy_data[2*k+1] = M::ee_op(&self.data[2*k+1], &self.lazy_data[k]);
            }
            self.lazy_data[k] = None;
        }
    }

    pub fn lazy_update(&mut self, a: usize, b: usize, l: usize, r: usize, k: usize, value: T) {
        self.eval(l,r,k);
        if b<=l || r<=a {return;}
        if a<=l && r<=b {
            self.lazy_data[k] = M::ee_op(&self.lazy_data[k], &Some(value));
            self.eval(l,r,k);
        }
        else{
            self.lazy_update(a,b,l,(l+r)/2,2*k+0,value.clone());
            self.lazy_update(a,b,(l+r)/2,r,2*k+1,value.clone());
            self.data[k] = M::tt_op(&self.data[2*k+0], &self.data[2*k+1]);
        }
    }

    pub fn update(&mut self, a: usize, b:usize, value: T){
		let sz = self.size_p2;
        self.lazy_update(a,b,0,sz,1,value);
    }

    pub fn lazy_query(&mut self, a: usize, b: usize, l: usize, r: usize, k: usize) -> Option<T> {
        self.eval(l,r,k);
        if a<=l && r<=b {return self.data[k].clone();}
        if b<=l || r<=a {return None;}
        let res1 = self.lazy_query(a, b, l, (l+r)/2, 2*k+0);
        let res2 = self.lazy_query(a, b, (l+r)/2, r, 2*k+1);
        M::tt_op(&res1, &res2)
    }

    pub fn query(&mut self, l: usize, r: usize) -> Option<T> {
		let sz = self.size_p2;
        self.lazy_query(l,r,0,sz,1)
    }
}

#[derive(Clone,Copy,Eq)]
struct Tuple {
	val: i64,
	idx: usize,
}

impl Add for Tuple {
	type Output = Tuple;
	fn add(self, other: Self) -> Tuple {
		Tuple {val: self.val + other.val, idx: self.idx}
	}
}

impl Ord for Tuple {
	fn cmp(&self, other: &Self) -> Ordering {
        self.val.cmp(&other.val)
    }
}

impl PartialOrd for Tuple {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Tuple {
    fn eq(&self, other: &Self) -> bool {
        self.val == other.val
    }
}


fn solve() {
	let n = read!(usize);
	let a = read!([i64]);
	let b = read!([i64]);
	let mut c = (0..n).map(|x| Tuple{val: b[x], idx: x}).collect::<Vec<Tuple>>();
	pub type Seg<T> = SegmentTree<SegOp<T>, T>;
	let mut seg = Seg::from_vec(c.clone());
	let mut ans = 0;
	loop {
		let t = seg.query(0,n).unwrap();
		if t.val==0 {
			break;
		}
		let l = (t.idx+n-1)%n;
		let r = (t.idx+1)%n;
		let mut sum = c[l].val + c[r].val;
		if c[l].val==0 {sum+=a[l];}
		if c[r].val==0 {sum+=a[r];}
		if a[t.idx]>t.val {
			println!("-1");
			return;
		}
		if a[t.idx]>=sum {
			if a[t.idx]%sum != t.val%sum {
				println!("-1");
				return;
			}
			else{
				c[t.idx] = Tuple{val: 0, idx: t.idx};
				seg.update(t.idx,t.idx+1,c[t.idx]);		
				ans += (t.val-a[t.idx])/sum;		
			}
		}
		else {
			if t.val<sum {
				if a[t.idx]!=t.val {
					println!("-1");
					return;
				}
			}
			let mut tmp = t.val%sum;
			if tmp==a[t.idx] {tmp=0;}
			c[t.idx] = Tuple{val: tmp, idx: t.idx};
			seg.update(t.idx,t.idx+1,c[t.idx]);
			ans += t.val/sum;
		}
		// println!("{} {} {} {}", t.idx,t.val,sum, c[t.idx].val);
	}
	println!("{}", ans);
}

fn run() {
    solve();
}


Measured memory_bytes: 41496