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 Rust (1.42.0) (judge verdict: Accepted)

use std::*;
use std::io::*;
use std::iter::Iterator;
use std::str::FromStr;
#[allow(unused_imports)]
use std::fmt::{Display, Formatter};

#[allow(dead_code)]
fn main() {
  let stdin = stdin();
  let r = &mut BufReader::new(stdin.lock());
  let stdout = stdout();
  let w = &mut BufWriter::new(stdout.lock());
  let stderr = stderr();
  let err = &mut BufWriter::new(stderr.lock());
  run(r, w, err);
  w.flush().unwrap();
  err.flush().unwrap();
}

macro_rules! _ft { () => (impl FnOnce(&mut Cursor<Vec<u8>>, &mut Vec<u8>, &mut Vec<u8>)); }

#[allow(dead_code)]
fn test(input: &str, output: &str, f: _ft!()) {
  let r = &mut Cursor::new(input.as_bytes().to_vec());
  let w: &mut Vec<u8> = &mut Vec::new();
  let err: &mut Vec<u8> = &mut Vec::new();
  f(r, w, err);
  let mut stderr = stderr();
  writeln!(stderr, "{}", String::from_utf8(err.to_vec()).unwrap()).unwrap();
  stderr.flush().ok();
  assert_eq!(String::from_utf8(w.to_vec()).unwrap().trim(), output.trim())
}

#[allow(unused_macros)]
macro_rules! t {
  ($f: ident => $input: expr, $output: expr) => (
    #[test]
    fn $f() { test($input, $output, run); }
  );
}

macro_rules! _display_st {
    ($f: expr; $name: expr, ) => (write!($f, "{}", $name)?);
    ($f: expr; $name: expr) => (_display_st!($f; $name, ));
    ($f: expr; $name: expr, $($rest: expr),+, ) => (
      _display_st!($f; $name);
      write!($f, " ")?;
      _display_st!($f; $($rest, )+);
    );
    ($f: expr; $name: expr, $($rest: expr),+) => (_display_st!($f; $name, $($rest, )+));
}

macro_rules! _st_iter_parse {
  ($iter: expr; $($p: ident : $t: ty),+; ) => (Self {
    $($p: $iter.next().unwrap().parse::<$t>().unwrap(), )+
  });
  ($iter: expr; $($p: ident : $t: ty),+; 1~) => (Self {
    $($p: $iter.next().unwrap().parse::<$t>().unwrap() - 1, )+
  });
}

/// 構造体を作成する
#[allow(unused_macros)]
macro_rules! st {
  ($name: ident => $($p: ident : $t: ty),+; $($rest: tt)*) => (
    struct $name { $($p : $t),+ }
    impl FromStr for $name {
      type Err = ();
      fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        let mut iter = s.split_whitespace();
        Ok(_st_iter_parse!(iter; $($p : $t),+; $($rest)*))
      }
    }
    impl Display for $name {
      fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        _display_st!(f; $(&self.$p, )+);
        Ok(())
      }
    }
  );
  ($name: ident => $($p: ident : $t: ty),+) => (st!($name => $($p : $t),+; ););

  ($name: ident => $($($p: ident),+: $t: ty);+) => (st!($name => $($($p : $t),+),+););
  ($name: ident => $($($p: ident),+: $($t: ty),+);+) => (st!($name => $($($p : $t),+),+););
  ($name: ident => $($p: ident),+: $t: ty) => (st!($name => $($p : $t),+););
  ($name: ident => $($p: ident),+: $($t: ty),+) => (st!($name => $($p : $t),+););

  ($name: ident => $($($p: ident),+: $t: ty);+; $($rest: tt)*) => (
    st!($name => $($($p : $t),+),+; $($rest)*);
  );
  ($name: ident => $($($p: ident),+: $($t: ty),+);+; $($rest: tt)*) => (
    st!($name => $($($p : $t),+),+; $($rest)*);
  );
  ($name: ident => $($p: ident),+: $t: ty; $($rest: tt)*) => (
    st!($name => $($p : $t),+; $($rest)*);
  );
  ($name: ident => $($p: ident),+: $($t: ty),+; $($rest: tt)*) => (
    st!($name => $($p : $t),+; $($rest)*);
  );
}

fn _read_iter<R: Read>(reader: &mut R) -> impl Iterator<Item=char> + '_ {
  reader.by_ref()
    .bytes()
    .map(|c| c.unwrap() as char)
    .skip_while(|c| c.is_whitespace())
}

#[allow(dead_code)]
fn read<F: FromStr, R: Read>(reader: &mut R) -> F {
  let str = _read_iter(reader).take_while(|c| !c.is_whitespace()).collect::<String>();
  str.parse::<F>().ok().unwrap()
}

#[allow(dead_code)]
fn read_line<F: FromStr, R: Read>(reader: &mut R) -> F {
  let str = _read_iter(reader).take_while(|c| c != &'\n').collect::<String>();
  let str = if str.ends_with('\r') { &str[0..str.len() - 1] } else { &str };
  str.parse::<F>().ok().unwrap()
}

#[allow(dead_code)]
fn read1<R: Read, T>(reader: &mut R, mut f: impl FnMut(char) -> T) -> T {
  f(_read_iter(reader).next().unwrap())
}

#[allow(dead_code)]
fn read1_line<R: Read, T>(reader: &mut R, f: impl FnMut(char) -> T) -> Vec<T> {
  _read_iter(reader).take_while(|c| c != &'\n').map(f).collect::<Vec<_>>()
}

/// 1要素読む
#[allow(unused_macros)]
macro_rules! r {
  ($stream: expr) => (read::<String, _>($stream));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));

  ($stream: expr; $t: ty) => (read::<$t, _>($stream));
  ($stream: expr; $t: ty; 1~) => (r!($stream; $t) - 1);

  ($stream: expr; $($t: ty),+) => (($(r!($stream; $t)),*));
  ($stream: expr; $($t: ty),+; 1~) => (($(r!($stream; $t) - 1),*));

  ($stream: expr; $t: ty; $n: expr) => (
    (0..$n).map(|_| r!($stream; $t)).collect::<Vec<_>>()
  );
  ($stream: expr; $t: ty; $n: expr; 1~) => (
    (0..$n).map(|_| r!($stream; $t) - 1).collect::<Vec<_>>()
  );

  ($stream: expr; $t: ty; $h: expr, $w: expr) => (
    (0..$h).map(|_| (0..$w).map(|_| r!($stream; $t)).collect::<Vec<_>>()).collect::<Vec<_>>()
  );
  ($stream: expr; $t: ty; $h: expr, $w: expr; 1~) => (
    (0..$h).map(|_| (0..$w).map(|_| r!($stream; $t) - 1).collect::<Vec<_>>()).collect::<Vec<_>>()
  );
}

/// 1文字読む
#[allow(unused_macros)]
macro_rules! r1 {
  ($stream: expr) => (read1($stream, |c| c));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));
  ($stream: expr; $f: expr) => (read1($stream, $f));
  ($stream: expr; $f: expr; ) => (r1!($stream, $f));
  ($stream: expr; $f: expr; $n: expr) => ((0..$n).map(|_| r1!($stream; $f)).collect::<Vec<_>>());
  ($stream: expr; $f: expr; $h: expr, $w: expr) => (
    (0..$h).map(|_| (0..$w).map(|_| r1!($stream; $f)).collect::<Vec<_>>()).collect::<Vec<_>>()
  );

  ($stream: expr; @$c: tt; $($tt: tt)*) => (
   r1!($stream; |c| c == stringify!($c).chars().next().unwrap(); $($tt)*)
  );
  ($stream: expr; @$c: tt/$_c: tt; $($tt: tt)*) => (r1!($stream; @$c; $($tt)*));
}

/// 1行読む
#[allow(unused_macros)]
macro_rules! rl {
  ($stream: expr) => (read_line::<String, _>($stream));
  ($stream: expr, ) => (r!($stream));
  ($stream: expr; ) => (r!($stream));
  ($stream: expr; $t: ty) => (read_line::<$t,  _>($stream));
  ($stream: expr; $t: ty; $n: expr) => ((0..$n).map(|_| rl!($stream; $t)).collect::<Vec<_>>());
}

macro_rules! _writes {
  ($stream: expr; $arg0: expr, $($arg: expr),*) => ({
    write!($stream, "{}", $arg0).ok();
    $(write!($stream, " {}", $arg).ok();)*
  });
}

/// 変数を出力
#[allow(unused_macros)]
macro_rules! w {
  ($stream: expr) => (write!($stream, " ").ok());
  ($stream: expr; ) => (w!($stream));
  ($stream: expr, ) => (w!($stream));

  ($stream: expr; $arg: expr) => (write!($stream, "{}", $arg).ok());
  ($stream: expr; $arg: expr, ) => (w!($stream; $arg));

  ($stream: expr; $arg0: expr, $($arg: expr),+) => (_writes!($stream; $arg0, $($arg),+));
  ($stream: expr; $arg0: expr, $($arg: expr),+, ) => (w!($stream; $arg0, $($arg),*));

  ($stream: expr, $($arg: tt)*) => (write!($stream, $($arg)*).ok());
}

/// 変数を改行付きで出力
#[allow(unused_macros)]
macro_rules! wl {
  ($stream: expr) => (writeln!($stream).ok());
  ($stream: expr, ) => (wl!($stream));
  ($stream: expr; ) => (wl!($stream));

  ($stream: expr; $arg: expr) => (writeln!($stream, "{}", $arg).ok());
  ($stream: expr; $arg: expr, ) => (wl!($stream; $arg));

  ($stream: expr; $arg0: expr, $($arg: expr),+) => ({
    _writes!($stream; $arg0, $($arg),+);
    wl!($stream)
  });
  ($stream: expr; $arg0: expr, $($arg: expr),+, ) => (wl!($stream; $arg0, $($arg),*));

  ($stream: expr, $($arg: tt)*) => (writeln!($stream, $($arg)*).ok());
}

/// ベクタを出力
#[allow(unused_macros)]
macro_rules! w_vec {
  ($stream: expr; $vec: expr) => (w_vec!($stream; $vec; $vec.len()));
  ($stream: expr; $vec: expr; $($tt: tt)*) => (w_vec!($stream; $vec => |e| e, " "; $($tt)*));

  ($stream: expr; $vec: expr => $f: expr) => (w_vec!($stream; $vec => $f; $vec.len()));
  ($stream: expr; $vec: expr => $f: expr; $($tt: tt)*) => (
    w_vec!($stream; $vec => $f, ""; $($tt)*)
  );

  ($stream: expr; $vec: expr => $f: expr, $del: expr; $n: expr) => (
    w!($stream; $f($vec[0]));
    for i in 1..$n { w!($stream, "{}{}", $del, $f($vec[i as usize])); }
    wl!($stream);
  );
  ($stream: expr; $vec: expr => $f: expr, $del: expr; $h: expr, $w: expr) => (
    for i in 0..$h { w_vec!($stream; $vec[i as usize] => $f, $del; $w); }
  );

  ($stream: expr; $vec: expr => String) => (w_vec!($stream; $vec => |c| c as char; $vec.len()));
  ($stream: expr; $vec: expr => String; $($tt: tt)*) => (
    w_vec!($stream; $vec => |c| c as char; $($tt)*)
  );

  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt) => (
    w_vec!($stream; $vec => @$c_t/$c_f; $vec.len())
  );
  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt; $($tt: tt)*) => (
    w_vec!($stream; $vec => |e| if e {stringify!($c_t)} else {stringify!($c_f)}; $($tt)*)
  );
}

/// ベクタを改行付きで出力
#[allow(unused_macros)]
macro_rules! wl_vec {
  ($stream: expr; $vec: expr) => (w_vec!($stream; $vec => |e| e, "\n"; $vec.len()));
  ($stream: expr; $vec: expr; $($tt: tt)*) => (w_vec!($stream; $vec => |e| e, "\n"; $($tt)*));
  ($stream: expr; $vec: expr => $f: expr) => (w_vec!($stream; $vec => $f, "\n"; $vec.len()));
  ($stream: expr; $vec: expr => $f: expr; $($tt: tt)*) => (
    w_vec!($stream; $vec => $f, "\n"; $($tt)*)
  );

  ($stream: expr; $vec: expr => 1~) => (wl_vec!($stream; $vec => |e| e + 1; $vec.len()));
  ($stream: expr; $vec: expr => 1~; $($tt: tt)*) => (
    w_vec!($stream; $vec => |e| e + 1, "\n"; $($tt)*)
  );

  ($stream: expr; $vec: expr => String) => (
    wl_vec!($stream; $vec => |c| c as char, "\n"; $vec.len())
  );
  ($stream: expr; $vec: expr => String; $($tt: tt)*) => (
    w_vec!($stream; $vec => |c| c as char, "\n"; $($tt)*)
  );

  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt) => (
    wl_vec!($stream; $vec => @$c_t/$c_f; $vec.len())
  );
  ($stream: expr; $vec: expr => @$c_t: tt/$c_f: tt; $($tt: tt)*) => (
    w_vec!($stream; $vec => |e| if e {stringify!($c_t)} else {stringify!($c_f)}, "\n"; $($tt)*)
  );
}

/// 早期リターン
#[allow(unused_macros)]
macro_rules! early { ($($t: tt)*) => ({ w!($($t)*); return; }); }

/// 配列の初期化
#[allow(unused_macros)]
macro_rules! v {
  ($elem: expr; $n: expr) => (vec![$elem; $n as usize]);
  ($elem: expr; $h: expr, $w: expr) => (vec![vec![$elem; $w as usize]; $h as usize]);
}

// start: Copied Libraries

trait VecAlias<T> {
  fn get_(&mut self, key: usize) -> &T;
  fn set(&mut self, key: usize, value: T);
  fn select<U>(&self, f: impl FnMut(&T) -> U) -> Vec<U>;
}

impl<T> VecAlias<T> for Vec<T> {
  fn get_(&mut self, key: usize) -> &T {
    self.get_mut(key).unwrap()
  }
  fn set(&mut self, key: usize, value: T) {
    self[key] = value;
  }
  fn select<U>(&self, mut f: impl FnMut(&T) -> U) -> Vec<U> {
    self.iter().map(|i| f(i)).collect::<Vec<_>>()
  }
}

trait VecOrdAlias<T> {
  fn asc(&mut self);
  fn desc(&mut self);
}

impl<T: Ord> VecOrdAlias<T> for Vec<T> {
  fn asc(&mut self) { self.sort_unstable(); }
  fn desc(&mut self) { self.sort_unstable_by(|i, j| j.cmp(i)); }
}

// end: Copied Libraries

#[allow(unused_variables)]
fn run<R: Read, W: Write, E: Write>(r_: &mut R, w_: &mut W, err: &mut E) {
  let n = r!(r_; i64);
  let a = r!(r_; i64; n);
  let mut v1 = v!(0i64; n + 1);
  let mut v2 = v!(0i64; n + 1);
  for i1 in 0..n {
    let i = i1 + 1;
    let v1_i = i + a[i1 as usize];
    if v1_i <= n { v1[v1_i as usize] += 1; }
    let v2_i = i - a[i1 as usize];
    if v2_i >= 0 { v2[v2_i as usize] += 1; }
  }

  let ans = v1.iter().zip(v2)
    .map(|(&i, j)| i * j)
    .collect::<Vec<_>>();
  let ans: i64 = ans.iter().sum();
  w!(w_; ans);
}

t!(te1 => r"6
2 3 3 1 3 1", r"3");
t!(te2 => r"6
5 2 4 2 8 8", r"0");
t!(te3 => r"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", r"22");