#[doc = " https://github.com/hatoo/competitive-rust-snippets"]
#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
#[allow(unused_imports)]
use std::io::{stdin, stdout, BufWriter, Write};
#[allow(unused_imports)]
use std::iter::FromIterator;
#[macro_export]
macro_rules ! chmax { ( $ x : expr , $ ( $ v : expr ) ,+ ) => { $ ( $ x = std :: cmp :: max ( $ x ,$ v ) ; ) + } ; }
#[macro_export]
macro_rules ! chmin { ( $ x : expr , $ ( $ v : expr ) ,+ ) => { $ ( $ x = std :: cmp :: min ( $ x ,$ v ) ; ) + } ; }
#[macro_export]
macro_rules ! max { ( $ x : expr ) => ( $ x ) ; ( $ x : expr , $ ( $ xs : expr ) ,+ ) => { std :: cmp :: max ( $ x , max ! ( $ ( $ xs ) ,+ ) ) } ; }
#[macro_export]
macro_rules ! min { ( $ x : expr ) => ( $ x ) ; ( $ x : expr , $ ( $ xs : expr ) ,+ ) => { std :: cmp :: min ( $ x , min ! ( $ ( $ xs ) ,+ ) ) } ; }
#[macro_export]
macro_rules ! dvec { ( $ t : expr ; $ len : expr ) => { vec ! [ $ t ; $ len ] } ; ( $ t : expr ; $ len : expr , $ ( $ rest : expr ) ,* ) => { vec ! [ dvec ! ( $ t ; $ ( $ rest ) ,* ) ; $ len ] } ; }
#[allow(unused_macros)]
macro_rules ! debug { ( $ ( $ a : expr ) ,* ) => { eprintln ! ( concat ! ( $ ( stringify ! ( $ a ) , " = {:?}, " ) ,* ) , $ ( $ a ) ,* ) ; } }
#[macro_export]
macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut parser = Parser :: from_str ( $ s ) ; input_inner ! { parser , $ ( $ r ) * } } ; ( parser = $ parser : ident , $ ( $ r : tt ) * ) => { input_inner ! { $ parser , $ ( $ r ) * } } ; ( new_stdin_parser = $ parser : ident , $ ( $ r : tt ) * ) => { let stdin = std :: io :: stdin ( ) ; let reader = std :: io :: BufReader :: new ( stdin . lock ( ) ) ; let mut $ parser = Parser :: new ( reader ) ; input_inner ! { $ parser , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { input ! { new_stdin_parser = parser , $ ( $ r ) * } } ; }
#[macro_export]
macro_rules ! input_inner { ( $ parser : ident ) => { } ; ( $ parser : ident , ) => { } ; ( $ parser : ident , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ parser , $ t ) ; input_inner ! { $ parser $ ( $ r ) * } } ; }
#[macro_export]
macro_rules ! read_value { ( $ parser : ident , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ parser , $ t ) ) ,* ) } ; ( $ parser : ident , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ parser , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ parser : ident , chars ) => { read_value ! ( $ parser , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ parser : ident , usize1 ) => { read_value ! ( $ parser , usize ) - 1 } ; ( $ parser : ident , $ t : ty ) => { $ parser . next ::<$ t > ( ) . expect ( "Parse error" ) } ; }
use std::io;
use std::io::BufRead;
use std::str;
pub struct Parser<R> {
    reader: R,
    buf: Vec<u8>,
    pos: usize,
}
impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}
impl<R: BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len, complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                if len == 0 {
                    break;
                }
                (len, buf2[len - 1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return str::from_utf8(&self.buf[begin..end]).unwrap().parse::<T>();
            } else {
                self.update_buf();
            }
        }
    }
}
#[allow(unused_macros)]
macro_rules ! debug { ( $ ( $ a : expr ) ,* ) => { eprintln ! ( concat ! ( $ ( stringify ! ( $ a ) , " = {:?}, " ) ,* ) , $ ( $ a ) ,* ) ; } }
#[doc = " https://github.com/hatoo/competitive-rust-snippets"]
const BIG_STACK_SIZE: bool = true;
#[allow(dead_code)]
fn main() {
    use std::thread;
    if BIG_STACK_SIZE {
        thread::Builder::new()
            .stack_size(32 * 1024 * 1024)
            .name("solve".into())
            .spawn(solve)
            .unwrap()
            .join()
            .unwrap();
    } else {
        solve();
    }
}
fn solve() {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());

    input!{
        n:usize,k:i64,
        a:[i64;n],
    }

    let mut cum1 = CumSum1::new(n);
    for i in 0..n {
        cum1.set(i,a[i]);
    }
    cum1.build();

    let mut v = vec![0;n+1];
    for i in 0..n {
        let x = cum1.query(0, i+1);
        v[i+1] = (x - (i+1) as i64) % k;
    }

    let mut wm = WMI::new(v.clone());
    let mut cnt = 0;
    for j in 1..n+1 {
        let x = v[j];
        let l = max(0, j as i64 + 1 - k) as usize;
        let r = j;
        cnt += wm.rangefreq(l, r, x, x+1);
    }
    println!("{}", cnt);
}

struct CumSum1 {
    base: Vec<i64>,
    dp: Vec<i64>,
}
impl CumSum1 {
    fn new(n: usize) -> CumSum1 {
        CumSum1 {
            base: vec![0; n],
            dp: vec![],
        }
    }
    fn add(&mut self, i: usize, x: i64) {
        self.base[i] += x;
    }
    fn set(&mut self, i: usize, x: i64) {
        self.base[i] = x;
    }
    fn build(&mut self) {
        let n = self.base.len();
        let mut dp = vec![0; n + 1];
        let mut acc = 0;
        for i in 0..n {
            acc += self.base[i];
            dp[i + 1] = acc;
        }
        self.dp = dp;
    }
    #[doc = "[i,j)"]
    fn query(&self, i: usize, j: usize) -> i64 {
        self.dp[j] - self.dp[i]
    }
}

#[doc = "lower,upper are inclusive range"]
pub struct BinarySearch<F> {
    pub p: F,
    pub lower: i64,
    pub upper: i64,
}
impl<F: Fn(i64) -> bool> BinarySearch<F> {
    #[doc = "O(log(upper-lower))"]
    pub fn lower_bound(&self) -> i64 {
        let lower = self.lower;
        let upper = self.upper;
        assert!(lower <= upper);
        let mut lb = lower - 1;
        let mut ub = upper + 1;
        while ub - lb > 1 {
            let mid = (lb + ub) / 2;
            if (self.p)(mid) {
                ub = mid;
            } else {
                lb = mid;
            }
        }
        let latter = ub;
        latter
    }
}

#[derive(Clone)]
struct FID {
    n: usize,
    n_blocks: usize,
    blocks: Vec<u64>,
    block_rank1: Vec<usize>,
}
impl FID {
    fn popcount(x: u64) -> usize {
        u64::count_ones(x) as usize
    }
    fn kpopi(x: u64, k: usize) -> usize {
        let mut x = x;
        let mut k = k;
        let mut ans = 64;
        for i in 0..64 {
            if x & (1 << i) > 0 {
                k -= 1;
            }
            if k == 0 {
                ans = i;
                break;
            }
        }
        ans
    }
    pub fn new(n: usize) -> FID {
        let n_blocks = (n >> 6) + 1;
        FID {
            n: n,
            n_blocks: (n >> 6) + 1,
            blocks: vec![0; n_blocks],
            block_rank1: vec![0; n_blocks],
        }
    }
    pub fn set(&mut self, k: usize) {
        self.blocks[k >> 6] |= 1 << (k & 0b111111);
    }
    pub fn build(&mut self) {
        self.block_rank1[0] = 0;
        for i in 1..self.n_blocks {
            self.block_rank1[i] = self.block_rank1[i - 1] + Self::popcount(self.blocks[i - 1]);
        }
    }
    pub fn access(&self, k: usize) -> bool {
        let x = self.blocks[k >> 6] & 1 << (k & 0b111111);
        if x > 0 {
            true
        } else {
            false
        }
    }
    #[doc = "count 1s in [0,k)"]
    pub fn rank1(&self, k: usize) -> usize {
        let mask = (1 << (k & 0b111111)) - 1;
        let rest = self.blocks[k >> 6] & mask;
        self.block_rank1[k >> 6] + Self::popcount(rest)
    }
    #[doc = "count 0s in [0,k). O(1)"]
    pub fn rank0(&self, k: usize) -> usize {
        k - self.rank1(k)
    }
    pub fn rank(&self, b: bool, k: usize) -> usize {
        if b {
            self.rank1(k)
        } else {
            self.rank0(k)
        }
    }
    #[doc = "query the index of k-th 0 (0-indexed)"]
    pub fn select0(&self, k: usize) -> usize {
        let bs = BinarySearch {
            lower: 0,
            upper: (self.n - 1) as i64,
            p: |i: i64| {
                let r = self.rank0(i as usize);
                r >= k + 1
            },
        };
        bs.lower_bound() as usize - 1
    }
    #[doc = "query the index of k-th 1 (0-indexed)"]
    pub fn select1(&self, k: usize) -> usize {
        let bs = BinarySearch {
            lower: 0,
            upper: (self.n - 1) as i64,
            p: |i: i64| {
                let r = self.rank1(i as usize);
                r >= k + 1
            },
        };
        bs.lower_bound() as usize - 1
    }
    pub fn select(&self, b: bool, k: usize) -> usize {
        if b {
            self.select1(k)
        } else {
            self.select0(k)
        }
    }
}
struct WM {
    mat: Vec<FID>,
    nzeros: Vec<usize>,
}
impl WM {
    pub fn new(xs: Vec<u64>) -> WM {
        let n = xs.len();
        let mut mat = vec![];
        let mut nzeros = vec![];
        let mut cur = xs;
        for i in 0..64 {
            let mid = 1 << (63 - i);
            let mask = mid - 1;
            let mut b = vec![];
            let mut left = vec![];
            let mut right = vec![];
            for i in 0..n {
                let x = cur[i];
                if x >= mid {
                    right.push(x & mask);
                    b.push(true);
                } else {
                    left.push(x & mask);
                    b.push(false);
                }
            }
            nzeros.push(left.len());
            left.append(&mut right);
            cur = left;
            let mut fid = FID::new(n);
            for i in 0..n {
                if b[i] {
                    fid.set(i);
                }
            }
            fid.build();
            mat.push(fid);
        }
        WM {
            mat: mat,
            nzeros: nzeros,
        }
    }
    #[doc = "counting x in v[0,i) O(1)"]
    pub fn rank(&self, x: u64, i: usize) -> usize {
        let mut s = 0;
        let mut e = i;
        for d in 0..64 {
            let fid = &self.mat[d];
            let b = x & (1 << (63 - d)) > 0;
            s = fid.rank(b, s);
            e = fid.rank(b, e);
            if b {
                s += self.nzeros[d];
                e += self.nzeros[d];
            }
        }
        e - s
    }
    #[doc = "the position of k-th x (0-indexed). O(logn)"]
    pub fn select(&self, x: u64, k: usize) -> usize {
        let bs = BinarySearch {
            lower: 0,
            upper: (self.mat[0].n - 1) as i64,
            p: |i: i64| {
                let cnt = self.rank(x, i as usize);
                cnt >= k + 1
            },
        };
        bs.lower_bound() as usize - 1
    }
    #[doc = "k-th largest number in [l,r)"]
    pub fn quantile(&self, l: usize, r: usize, k: usize) -> u64 {
        let mut res = 0;
        let mut k = k;
        let mut s = l;
        let mut e = r;
        for d in 0..64 {
            let msb = 1 << (63 - d);
            let fid = &self.mat[d];
            let ns = fid.rank1(s);
            let ne = fid.rank1(e);
            let n1 = ne - ns;
            if n1 >= k {
                res |= msb;
                s = ns;
                e = ne;
                s += self.nzeros[d];
                e += self.nzeros[d];
            } else {
                s = s - ns;
                e = e - ne;
                k -= n1;
            }
        }
        res
    }
    pub fn rank_all(&self, l: usize, r: usize, x: u64) -> (usize, usize, usize) {
        let mut cnt_lt = 0;
        let mut cnt_gt = 0;
        let mut s = l;
        let mut e = r;
        for d in 0..64 {
            let b = x & (1 << (63 - d)) > 0;
            let lcnt = self.mat[d].rank(b, s);
            let rcnt = self.mat[d].rank(b, e);
            let add = (e - s) - (rcnt - lcnt);
            if b {
                cnt_lt += add;
            } else {
                cnt_gt += add;
            }
            s = lcnt;
            e = rcnt;
            if b {
                s += self.nzeros[d];
                e += self.nzeros[d];
            }
        }
        (cnt_lt, e - s, cnt_gt)
    }
    #[doc = "counting numbers in range [min,max) in v[l,r). O(1)"]
    pub fn rangefreq(&self, l: usize, r: usize, min: u64, max: u64) -> usize {
        let (cntlt_max, _, _) = self.rank_all(l, r, max);
        let (cntlt_min, _, _) = self.rank_all(l, r, min);
        cntlt_max - cntlt_min
    }
}
struct WMI {
    offset: i64,
    wm: WM,
}
impl WMI {
    pub fn new(xs: Vec<i64>) -> WMI {
        let offset = 1 << 62;
        let mut ys = vec![];
        for x in xs {
            ys.push((x + offset) as u64)
        }
        let wm = WM::new(ys);
        WMI {
            offset: offset,
            wm: wm,
        }
    }
    pub fn rangefreq(&self, l: usize, r: usize, min: i64, max: i64) -> usize {
        self.wm
            .rangefreq(l, r, (min + self.offset) as u64, (max + self.offset) as u64)
    }
    pub fn quantile(&self, l: usize, r: usize, k: usize) -> i64 {
        self.wm.quantile(l, r, k) as i64 - self.offset
    }
    pub fn rank(&self, x: i64, i: usize) -> usize {
        self.wm.rank((x + self.offset) as u64, i)
    }
    pub fn select(&self, x: i64, k: usize) -> usize {
        self.wm.select((x + self.offset) as u64, k)
    }
}

Measured memory_bytes: 28152