/*******************************************************
1) InMobi OA — Minimum Active Towers in a Circle

Problem:
- n towers in a circle (0..n-1)
- activate i => neutralizes all towers within circular distance R[i] (including itself)
- find minimum activations to neutralize all towers

Idea:
- Convert each tower to a coverage interval on the circle
- Unroll circle to a line of length 2n
- Then solve "minimum intervals to cover a segment of length n"
- Greedy "extend farthest" + binary lifting (jump pointers) for speed

Time: O(n log n)
*******************************************************/

#include <bits/stdc++.h>                 // include almost all standard C++ headers (common in CP)
using namespace std;                     // avoid writing std:: everywhere

int main() {                             // program starts here
    ios::sync_with_stdio(false);         // faster I/O
    cin.tie(nullptr);                    // faster I/O

    int n;                               // number of towers
    cin >> n;                            // read n
    vector<long long> R(n);              // R[i] = radius for tower i (use long long for safety)
    for (int i = 0; i < n; i++) cin >> R[i]; // read all radii

    // If any tower covers the whole circle by itself, answer is 1.
    for (int i = 0; i < n; i++) {        // loop all towers
        if (2LL * R[i] + 1 >= n) {       // coverage size in circle is (2*R+1); if >= n => covers all
            cout << 1 << "\n";           // print 1 activation
            return 0;                    // exit early
        }
    }

    int P = 2 * n;                       // total "unrolled" positions: 0..2n-1 (we call that P)
    int LAST = P - 1;                    // last valid index in unrolled range is 2n-1

    vector<int> bestAtL(P, -1);          // bestAtL[l] = farthest right endpoint among intervals starting at l

    auto norm = [&](long long x) -> int { // function to wrap any integer x into [0..n-1]
        x %= n;                          // take modulo n
        if (x < 0) x += n;               // if negative, shift into positive range
        return (int)x;                   // return as int
    };

    // Build intervals for each tower i.
    for (int i = 0; i < n; i++) {        // go through each tower
        long long rad = R[i];            // radius of coverage

        long long rawL = (long long)i - rad; // left boundary (may be negative)
        long long rawR = (long long)i + rad; // right boundary (may exceed n-1)

        int L = norm(rawL);              // normalize left into [0..n-1]
        int RR = norm(rawR);             // normalize right into [0..n-1]

        // helper to add an interval [l, r] to bestAtL (clamped to our unrolled array)
        auto addInterval = [&](long long l, long long r) { // lambda function for adding interval
            if (l > LAST) return;        // if start is beyond useful range, ignore
            if (l < 0) return;           // safety check (shouldn't happen here)
            r = min<long long>(r, LAST); // clamp r to LAST so we don't go beyond array
            bestAtL[(int)l] = max(bestAtL[(int)l], (int)r); // keep only farthest reach for that start l
        };

        if (L <= RR) {                   // case 1: interval does NOT wrap around circle
            addInterval(L, RR);          // add interval in base copy [0..n-1]
            addInterval((long long)L + n, (long long)RR + n); // add same interval shifted by +n for unrolled copy
        } else {                         // case 2: interval wraps around (covers end and start of circle)
            addInterval(L, (long long)RR + n); // represent wrap as one continuous interval in unrolled line
            addInterval((long long)L + n, (long long)RR + 2LL * n); // second copy shifted by +n again
        }
    }

    vector<int> farthest(P, -1);         // farthest[x] = best reach among all intervals with start <= x
    for (int x = 0; x < P; x++) {        // build prefix maximum
        farthest[x] = bestAtL[x];        // start with interval that starts exactly at x
        if (x) farthest[x] = max(farthest[x], farthest[x - 1]); // also consider earlier starts (prefix max)
    }

    vector<int> nxt(P + 1, P);           // nxt[x] = next uncovered position after taking 1 greedy step
    for (int x = 0; x < P; x++) {        // compute nxt for each x
        if (farthest[x] < x) nxt[x] = x; // if we cannot even cover x, we're stuck (no progress)
        else nxt[x] = farthest[x] + 1;   // else jump to one past farthest covered point
    }
    nxt[P] = P;                          // if already at end, stay at end

    int LOG = 1;                         // number of levels for binary lifting
    while ((1 << LOG) <= P + 1) LOG++;   // increase LOG until 2^LOG is big enough

    vector<vector<int>> up(LOG, vector<int>(P + 1, P)); // up[j][x] = position after 2^j greedy steps
    up[0] = nxt;                         // base case: 2^0 = 1 step is nxt

    for (int j = 1; j < LOG; j++) {      // build higher jumps
        for (int x = 0; x <= P; x++) {   // for every position
            up[j][x] = up[j - 1][ up[j - 1][x] ]; // jump twice using previous layer
        }
    }

    const int INF = 1e9;                 // a large number for "min answer"
    int ans = INF;                       // store best answer

    // Try starting segment at each s in [0..n-1] covering [s, s+n-1]
    for (int s = 0; s < n; s++) {        // try each start
        int target = s + n;              // we want to reach at least this position (one past end)

        if (nxt[s] == s) continue;       // if stuck at start, skip

        int pos = s;                     // current position we need to cover
        int steps = 0;                   // number of activations used

        // Use binary lifting to take big jumps while still not reaching target
        for (int j = LOG - 1; j >= 0; j--) { // from largest jump down to smallest
            if (up[j][pos] < target) {   // if taking 2^j steps still keeps us before target
                pos = up[j][pos];        // apply the jump
                steps += (1 << j);       // add number of steps taken
            }
        }

        if (nxt[pos] == pos) continue;   // if we are stuck before finishing, skip
        steps++;                         // take one more greedy step
        pos = nxt[pos];                  // update position

        if (pos >= target) ans = min(ans, steps); // if covered full segment, update answer
    }

    cout << (ans == INF ? -1 : ans) << "\n"; // print answer (or -1 if impossible)
    return 0;                             // exit
}