Problem:
Score: 500 points

Problem Statement

You are the top spy of AtCoder Kingdom. To prevent the stolen secret from being handed to AlDebaran Kingdom, you have sneaked into the party where the transaction happens.

There are N attendees in the party, and they are given attendee numbers from 1 through N. The height of Attendee i is A_i.

According to an examination beforehand, you know that a pair of attendees satisfying the condition below will make the transaction.

The absolute difference of their attendee numbers is equal to the sum of their heights.

There are \frac{N(N-1)}{2} ways to choose two from the N attendees and make a pair. Among them, how many satisfy the condition above?

P.S.: We cannot let you know the secret.

Constraints

All values in input are integers.

2 \leq N \leq 2 \times 10^5

1 \leq A_i \leq 10^9\ (1 \leq i \leq N)

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 \dots A_N

Output

Print the number of pairs satisfying the condition.

Sample Input 1

6
2 3 3 1 3 1

Sample Output 1

3

A_1 + A_4 = 3, so the pair of Attendee 1 and 4 satisfy the condition.

A_2 + A_6 = 4, so the pair of Attendee 2 and 6 satisfy the condition.

A_4 + A_6 = 2, so the pair of Attendee 4 and 6 satisfy the condition.

No other pair satisfies the condition, so you should print 3.

Sample Input 2

6
5 2 4 2 8 8

Sample Output 2

0

No pair satisfies the condition, so you should print 0.

Sample Input 3

32
3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8 4 6 2 6 4 3 3 8 3 2 7 9 5

Sample Output 3

22

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.Intrinsics.X86;
using System.Text;
using static Solve.Methods;
using static Solve.Input;
using static Solve.Output;
using static System.Math;

namespace Solve
{
    public partial class Solver
    {
        public void Main() {
            int N = Int;
            var A = Int.array(N);
            Assert(N >= 2 && N <= 200000);
            Assert(A.All(a => a >= 1 && a <= 1000000000));


            var start_indexes = new List<int>[N];
            rep(N,i=>start_indexes[i]=new List<int>());
            for (int i = 0; i < N; i++) {
                int x = i + A[i];
                if (x < N) start_indexes[x].Add(i);
            }

            long ans = 0;

            for (int i = 0; i < N; i++) {
                var x = i - A[i];
                if (x < 0 || x >= N) continue;
                ans += start_indexes[x].Count;
            }
            
            print(ans);
        }
        

        const int MOD = 1_000_000_007;
    }
    
    public static class Methods
    {
        [MethodImpl(256)]
        public static bool Assert(in bool b, in string message = null) =>
            b ? true : throw new Exception(message ?? "Assert failed.");
        [MethodImpl(256)]
        public static string JoinSpace<T>(this IEnumerable<T> source) => source.Join(" ");
        [MethodImpl(256)]
        public static string JoinEndline<T>(this IEnumerable<T> source) => source.Join("\n");
        [MethodImpl(256)]
        public static string Join<T>(this IEnumerable<T> source, string s) =>
            string.Join(s, source);
        [MethodImpl(256)]
        public static string Join<T>(this IEnumerable<T> source, char c) =>
            string.Join(c.ToString(), source);
        public static long Gcd(long a, long b) {
            while (true) {
                if (a < b) (a, b) = (b, a);
                if (a % b == 0) return b;
                var x = a;
                a = b;
                b = x % b;
            }
        }
        public static long Lcm(long a, long b) => a / Gcd(a, b) * b;
        public static bool IsPrime(long value) {
            if (value <= 1) return false;
            for (long i = 2; i * i <= value; ++i)
                if (value % i == 0)
                    return false;
            return true;
        }
        public static long PowMod(long a, long b, long p) {
            long res = 1;
            while (b > 0) {
                if (b % 2 != 0) res = res * a % p;
                a = a * a % p;
                b >>= 1;
            }

            return res;
        }
        public static IEnumerable<long> Factors(long n) {
            Assert(n >= 0, "n must be greater than 0.");
            for (long i = 1; i * i <= n; ++i) {
                long div = DivRem(n, i, out long rem);
                if (rem > 0) continue;
                yield return div;
                if (i != div) yield return i;
            }
        }
        public static IEnumerable<int> Factors(int n) => Factors((long) n).Select(Convert.ToInt32);

        [MethodImpl(256)] public static int DivCeil(int a, int b) => (a + b - 1) / b;
        [MethodImpl(256)] public static long DivCeil(long a, long b) => (a + b - 1) / b;
        public static IEnumerable<T[]> Permutations<T>(IEnumerable<T> src) {
            var ret = new List<T[]>();
            Search(ret, new Stack<T>(), src.ToArray());
            return ret;

            static void Search(ICollection<T[]> perms, Stack<T> stack, T[] a) {
                int N = a.Length;
                if (N == 0) perms.Add(stack.Reverse().ToArray());
                else {
                    var b = new T[N - 1];
                    Array.Copy(a, 1, b, 0, N - 1);
                    for (int i = 0; i < a.Length; ++i) {
                        stack.Push(a[i]);
                        Search(perms, stack, b);
                        if (i < b.Length) b[i] = a[i];
                        stack.Pop();
                    }
                }
            }
        }
        public static long BinarySearch(long low,
            long high,
            Func<long, bool> expression
        ) {
            while (low < high) {
                long middle = (high - low) / 2 + low;
                if (!expression(middle))
                    high = middle;
                else
                    low = middle + 1;
            }

            return high;
        }
        public static int LowerBound<T>(T[] arr,
            int start,
            int end,
            T value,
            IComparer<T> comparer
        ) {
            int low = start;
            int high = end;
            while (low < high) {
                var mid = ((high - low) >> 1) + low;
                if (comparer.Compare(arr[mid], value) < 0)
                    low = mid + 1;
                else
                    high = mid;
            }

            return low;
        }
        public static int LowerBound<T>(T[] arr, T value)
            where T : IComparable {
            return LowerBound(arr, 0, arr.Length, value, Comparer<T>.Default);
        }
        public static int UpperBound<T>(T[] arr,
            int start,
            int end,
            T value,
            IComparer<T> comparer
        ) {
            int low = start;
            int high = end;
            while (low < high) {
                var mid = ((high - low) >> 1) + low;
                if (comparer.Compare(arr[mid], value) <= 0)
                    low = mid + 1;
                else
                    high = mid;
            }

            return low;
        }
        public static int UpperBound<T>(T[] arr, T value) {
            return UpperBound(arr, 0, arr.Length, value, Comparer<T>.Default);
        }
        [MethodImpl(256)]
        public static IEnumerable<TResult> Repeat<TResult>(TResult value,
            int count
        ) =>
            Enumerable.Repeat(value, count);
        [MethodImpl(256)]
        public static string AsString(this IEnumerable<char> source) =>
            new string(source.ToArray());
        [MethodImpl(256)]
        public static IEnumerable<long> CumSum(this IEnumerable<long> source) {
            long sum = 0;
            foreach (var item in source)
                yield return sum += item;
        }
        [MethodImpl(256)]
        public static IEnumerable<int> CumSum(this IEnumerable<int> source) {
            int sum = 0;
            foreach (var item in source)
                yield return sum += item;
        }
        [MethodImpl(256)] public static bool IsIn<T>(this T value, T l, T r)
            where T : IComparable<T> =>
            l.CompareTo(r) > 0
                ? throw new ArgumentException()
                : l.CompareTo(value) <= 0 && value.CompareTo(r) < 0;
        [MethodImpl(256)]
        public static bool IsIn(this in int value, in Range range) =>
            value.IsIn(range.Start.Value, range.End.Value);
        [MethodImpl(256)]
        public static bool IsIn(this in Index value, in Range range) =>
            value.IsFromEnd &&
            value.Value.IsIn(range.Start.Value, range.End.Value);
        [MethodImpl(256)]
        public static IEnumerable<int> Range(int start, int end, int step = 1) {
            for (var i = start; i < end; i += step) yield return i;
        }
        [MethodImpl(256)] public static IEnumerable<int> Range(int end) => Range(0, end);
        [MethodImpl(256)]
        public static IEnumerable<int> Range(Range range, int step = 1) =>
            Range(range.Start.Value, range.End.Value, step);
        [MethodImpl(256)] public static T[] Sort<T>(this T[] arr)
            where T : IComparable<T> {
            var array = arr[..];
            Array.Sort(array);
            return array;
        }
        [MethodImpl(256)]
        public static T[] Sort<T, U>(this T[] arr, Func<T, U> selector)
            where U : IComparable<U> {
            var array = arr[..];
            Array.Sort(array, (a, b) => selector(a).CompareTo(selector(b)));
            return array;
        }
        [MethodImpl(256)] public static T[] SortDescending<T>(this T[] arr)
            where T : IComparable<T> {
            var array = arr[..];
            Array.Sort(array, (a, b) => b.CompareTo(a));
            return array;
        }
        [MethodImpl(256)]
        public static T[] SortDescending<T, U>(this T[] arr,
            Func<T, U> selector
        ) where U : IComparable<U> {
            var array = arr[..];
            Array.Sort(array, (a, b) => selector(b).CompareTo(selector(a)));
            return array;
        }
        public static T[] Unique<T>(this IEnumerable<T> arr) {
            var source = arr.ToArray();
            var ret = new List<T>(source.Length);
            var set = new SortedSet<T>();
            ret.AddRange(source.Where(val => set.Add(val)));

            return ret.ToArray();
        }
        [MethodImpl(256)] public static bool chmin<T>(ref T a, T b)
            where T : IComparable<T> {
            if (a.CompareTo(b) > 0) {
                a = b;
                return true;
            }

            return false;
        }
        [MethodImpl(256)] public static bool chmax<T>(ref T a, T b)
            where T : IComparable<T> {
            if (a.CompareTo(b) < 0) {
                a = b;
                return true;
            }

            return false;
        }
        [MethodImpl(256)]
        public static T[][] JaggedArray2D<T>(int a,
            int b,
            T defaultValue = default
        ) {
            var ret = new T[a][];
            for (int i = 0; i < a; ++i)
                ret[i] = Enumerable.Repeat(defaultValue, b).ToArray();
            return ret;
        }
        [MethodImpl(256)]
        public static T[,] Array2D<T>(int a, int b, T defaultValue = default) {
            var ret = new T[a, b];
            for (int i = 0; i < a; ++i)
            for (int j = 0; j < b; ++j)
                ret[i, j] = defaultValue;
            return ret;
        }
        [MethodImpl(256)] public static T[,] To2DArray<T>(this T[][] array) {
            if (!array.Any()) return new T[0, 0];

            int len = array[0].Length;
            if (array.Any(x => x.Length != len))
                throw new ArgumentException("array の各要素の長さが異なります。",
                    nameof(array));

            var ret = new T[array.Length, len];
            for (int i = 0; i < array.Length; ++i)
            for (int j = 0; j < len; ++j)
                ret[i, j] = array[i][j];
            return ret;
        }
        [MethodImpl(256)] public static T Min<T>(params T[] col) => col.Min();
        [MethodImpl(256)] public static T Max<T>(params T[] col) => col.Max();
        [MethodImpl(256)]
        public static IEnumerable<(T, int)> WithIndex<T>(
            this IEnumerable<T> source
        ) =>
            source.Select((x, i) => (x, i));
        [MethodImpl(256)] public static (T, U, V)[] Zip<T, U, V>(
            IReadOnlyCollection<T> t,
            IReadOnlyCollection<U> u,
            IReadOnlyCollection<V> v
        ) {
            Assert(t.Count == u.Count && u.Count == v.Count);
            return t.Zip(u, (a, b) => (a, b))
                .Zip(v, (tuple, c) => (tuple.Item1, tuple.Item2, c)).ToArray();
        }
        [MethodImpl(256)]
        public static void rep(in int start, in int end, Action<int> func) {
            for (int i = start; i < end; ++i) func(i);
        }
        [MethodImpl(256)]
        public static void rep(in int end, Action<int> func) => rep(0, end, func);
        [MethodImpl(256)]
        public static void rep1(in int end, Action<int> func) => rep(1, end + 1, func);
        [MethodImpl(256)]
        public static void repr(in int end, Action<int> func) {
            for (int i = end - 1; i >= 0; --i) func(i);
        }
        [MethodImpl(256)]
        public static void each<T>(this IEnumerable<T> source, Action<T> func) {
            foreach (var item in source) func(item);
        }
        [MethodImpl(256)]
        public static void eachWithIndex<T>(this IEnumerable<T> source,
            Action<T, int> func
        ) {
            int index = 0;
            foreach (var item in source) func(item, index++);
        }
        [MethodImpl(256)] public static int bit(in int x) => 1 << x;
        [MethodImpl(256)] public static long bitl(in int x) => 1L << x;
    }
    public static class Caluclation
    {
        [MethodImpl(256)] public static int Addition(int a, int b) => a + b;
        [MethodImpl(256)] public static long Addition(long a, long b) => a + b;
        [MethodImpl(256)] public static double Addition(double a, double b) => a + b;
        [MethodImpl(256)] public static int Xor(int a, int b) => a ^ b;
        [MethodImpl(256)] public static long Xor(long a, long b) => a ^ b;
        [MethodImpl(256)] public static int Multiplication(int a, int b) => a * b;
        [MethodImpl(256)] public static long Multiplication(long a, long b) => a * b;
    }
    public class UnorderedMap<T, U> : Dictionary<T, U>
    {
        public new U this[T k] {
            get =>
                TryGetValue(k, out var v) ? v : base[k] = default;
            set =>
                base[k] = value;
        }
    }
    public class Map<T, U> : SortedDictionary<T, U>
    {
        public new U this[T k] {
            get =>
                TryGetValue(k, out var v) ? v : base[k] = default;
            set =>
                base[k] = value;
        }
    }
    public class Scanner<T>
    {
        public T r => next<T>();
        public T next() => r;

        private IEnumerable<T> enumerable(int N) {
            for (int i = 0; i < N; ++i) yield return r;
        }

        public T[] array(in int N) => enumerable(N).ToArray();
        public List<T> list(in int N) => enumerable(N).ToList();
        public T[,] array2d(in int N, in int M) => next2DArray<T>(N, M);
        public T[][] listArray(in int n) {
            var ret = new T[n][];
            for (int i = 0; i < n; i++) ret[i] = array(next<int>());
            return ret;
        }

        public void Deconstruct(out T _1, out T _2) => (_1, _2) = (r, r);
        public void Deconstruct(out T _1, out T _2, out T _3) => (_1, _2, _3) = (r, r, r);
        public void Deconstruct(out T _1, out T _2, out T _3, out T _4) =>
            (_1, _2, _3, _4) = (r, r, r, r);
        public void Deconstruct(out T _1,
            out T _2,
            out T _3,
            out T _4,
            out T _5
        ) =>
            (_1, _2, _3, _4, _5) = (r, r, r, r, r);
        public void Deconstruct(out T _1,
            out T _2,
            out T _3,
            out T _4,
            out T _5,
            out T _6
        ) =>
            (_1, _2, _3, _4, _5, _6) = (r, r, r, r, r, r);
        public void Deconstruct(out T _1,
            out T _2,
            out T _3,
            out T _4,
            out T _5,
            out T _6,
            out T _7
        ) =>
            (_1, _2, _3, _4, _5, _6, _7) = (r, r, r, r, r, r, r);
        public void Deconstruct(out T _1,
            out T _2,
            out T _3,
            out T _4,
            out T _5,
            out T _6,
            out T _7,
            out T _8
        ) =>
            (_1, _2, _3, _4, _5, _6, _7, _8) = (r, r, r, r, r, r, r, r);
        public void Deconstruct(
            out T _1,
            out T _2,
            out T _3,
            out T _4,
            out T _5,
            out T _6,
            out T _7,
            out T _8,
            out T _9
        ) =>
            (_1, _2, _3, _4, _5, _6, _7, _8, _9) = (r, r, r, r, r, r, r, r, r);
        public void Deconstruct(
            out T _1,
            out T _2,
            out T _3,
            out T _4,
            out T _5,
            out T _6,
            out T _7,
            out T _8,
            out T _9,
            out T _10
        ) =>
            (_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) =
            (r, r, r, r, r, r, r, r, r, r);
        
        public static implicit operator T(Scanner<T> sc) => sc.r;
    }
    public static class Input
    {
        private const char _separator = ' ';
        private static readonly Queue<string> _input = new Queue<string>();
        private static readonly StreamReader sr =
#if FILE
            new StreamReader("in.txt");
#else
            new StreamReader(Console.OpenStandardInput());
#endif

        public static string ReadLine => sr.ReadLine();
        public static string ReadStr => Read;
        public static int ReadInt => int.Parse(Read);
        public static long ReadLong => long.Parse(Read);
        public static ulong ReadULong => ulong.Parse(Read);
        public static double ReadDouble => double.Parse(Read);
        public static BigInteger ReadBigInteger => BigInteger.Parse(Read);

        public static string Read {
            get {
                if (_input.Any()) return _input.Dequeue();

                foreach (var val in sr.ReadLine().Split(_separator))
                    _input.Enqueue(val);

                return _input.Dequeue();
            }
        }

        public static string next() => Read;
        public static T next<T>() =>
            default(T) switch {
                sbyte _ => (T) (object) (sbyte) ReadInt,
                short _ => (T) (object) (short) ReadInt,
                int _ => (T) (object) ReadInt,
                long _ => (T) (object) ReadLong,
                byte _ => (T) (object) (byte) ReadULong,
                ushort _ => (T) (object) (ushort) ReadULong,
                uint _ => (T) (object) (uint) ReadULong,
                ulong _ => (T) (object) ReadULong,
                float _ => (T) (object) (float) ReadDouble,
                double _ => (T) (object) ReadDouble,
                string _ => (T) (object) ReadStr,
                char _ => (T) (object) ReadStr[0],
                BigInteger _ => (T) (object) ReadBigInteger,
                _ => typeof(T) == typeof(string)
                    ? (T) (object) ReadStr
                    : throw new NotSupportedException(),
            };
        public static (T, U) next<T, U>() => (next<T>(), next<U>());
        public static (T, U, V) next<T, U, V>() => (next<T>(), next<U>(), next<V>());
        public static (T, U, V, W) next<T, U, V, W>() =>
            (next<T>(), next<U>(), next<V>(), next<W>());
        public static (T, U, V, W, X) next<T, U, V, W, X>() =>
            (next<T>(), next<U>(), next<V>(), next<W>(), next<X>());

        public static T[] nextArray<T>(in int size) {
            var ret = new T[size];
            for (int i = 0; i < size; ++i) ret[i] = next<T>();
            return ret;
        }
        public static T[,] next2DArray<T>(int n, in int m) {
            var ret = new T[n, m];
            for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                ret[i, j] = next<T>();
            return ret;
        }
        public static (T[], U[]) nextArray<T, U>(in int size) {
            var ret1 = new T[size];
            var ret2 = new U[size];
            for (int i = 0; i < size; ++i) (ret1[i], ret2[i]) = next<T, U>();
            return (ret1, ret2);
        }
        public static (T[], U[], V[]) nextArray<T, U, V>(in int size) {
            var ret1 = new T[size];
            var ret2 = new U[size];
            var ret3 = new V[size];
            for (int i = 0; i < size; ++i)
                (ret1[i], ret2[i], ret3[i]) = next<T, U, V>();
            return (ret1, ret2, ret3);
        }
    }
    public static class Output
    {
        [MethodImpl(256)] public static void print() => Console.WriteLine();
        [MethodImpl(256)]
        public static void print(in string s, bool endline = true) {
            if (endline) Console.WriteLine(s);
            else Console.Write(s);
        }
        [MethodImpl(256)]
        public static void print(in int v, bool endline = true) {
            if (endline) Console.WriteLine(v);
            else Console.Write(v);
        }
        [MethodImpl(256)]
        public static void print(in long v, bool endline = true) {
            if (endline) Console.WriteLine(v);
            else Console.Write(v);
        }
        [MethodImpl(256)]
        public static void print(in ulong v, bool endline = true) {
            if (endline) Console.WriteLine(v);
            else Console.Write(v);
        }
        [MethodImpl(256)] public static void print(in bool b) => PrintBool(b);
        [MethodImpl(256)] public static void print(in object v) => Console.WriteLine(v);
        [MethodImpl(256)]
        public static void print<T>(in IEnumerable<T> array,
            string separator = " "
        ) =>
            Console.WriteLine(array.Join(separator));
        [MethodImpl(256)] public static void prints<T>(params T[] t) => print(t);
        
#if LOCAL
        [MethodImpl(256)]
        public static void debug<T>(in T value, bool endline = true) {
            if (endline) Console.WriteLine(value);
            else Console.Write(value);
        }
#else
        public static void debug(params object[] obj) { }
#endif

        private static void PrintBool(in bool val,
            in string yes = null,
            in string no = null
        ) =>
            print(val ? yes ?? _yes : no ?? _no);
        private static string _yes = "Yes", _no = "No";

        public static void SetYesNoString(in YesNoType t) => (_yes, _no) = YesNoString[t];
        public static void SetYesNoString(in string yes, in string no) => (_yes, _no) = (yes, no);

        private static readonly Dictionary<YesNoType, (string yes, string no)>
            YesNoString =
                new Dictionary<YesNoType, (string yes, string no)>() {
                    {YesNoType.Yes_No, ("Yes", "No")},
                    {YesNoType.YES_NO, ("YES", "NO")},
                    {YesNoType.Upper, ("YES", "NO")},
                    {YesNoType.yes_no, ("yes", "no")},
                    {YesNoType.Lower, ("yes", "no")},
                    {YesNoType.Possible_Impossible, ("Possible", "Impossible")},
                    {YesNoType.Yay, ("Yay!", ":(")},
                };

        public static readonly (string yes, string no)
            YN_Possible = ("Possible", "Impossible"),
            YN_lower = ("yes", "no"),
            YN_upper = ("YES", "NO"),
            YN_Yay = ("Yay!", ":(");

        public static void Yes() => print(_yes);
        public static void No() => print(_no);

        public static object cout {
            set => Console.WriteLine(value);
        }
#if LOCAL
        public static object dout {
            set => Console.WriteLine(value);
        }
#else
        public static object dout { set { } }
#endif
        public static object cerr {
            set => Console.Error.WriteLine(value);
        }

        public const string endl = "\n";

        public enum YesNoType { Yes_No, YES_NO, Upper, yes_no, Lower, Possible_Impossible, Yay }
    }
    public class Program
    {
        public static void Main(string[] args) {
            var sw = new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = false};
            Console.SetOut(sw);
            new Solver().Main();
            Console.Out.Flush();
        }
    }
    partial class Solver
    {
        readonly Scanner<int> Int;
        readonly Scanner<long> Long;
        readonly Scanner<string> String;
        public Solver() =>
            (Int, String, Long) = (new Scanner<int>(), new Scanner<string>(),
                new Scanner<long>());
        const int INF = 1000000010;
        const long LINF = 1000000000000000100;
        const double EPS = 1e-9;
        public static readonly int[] dx = {-1, 0, 0, 1}, dy = {0, 1, -1, 0};
    }
}