use proconio::input; use std::collections::BTreeMap; const H: u128 = 9007199254740997; fn main() { input! { n: usize, a: [i128; n], } let mut answer: u128 = n as u128; if n == 1 { println!("{}", answer); return; } let m = n - 1; let mut diff_a = Vec::with_capacity(m); for i in 0..m { diff_a.push(a[i + 1] - a[i]); } // 座標圧縮 let mut vals = diff_a.clone(); vals.sort(); vals.dedup(); let mut mp = BTreeMap::new(); for (i, v) in vals.iter().enumerate() { mp.insert(*v, (i + 1) as u128); } let diff_a2: Vec = diff_a.iter().map(|x| mp[x]).collect(); let max_a = *diff_a2.iter().max().unwrap(); let b_base = max_a + 1; // forward hash let mut forward_hash = vec![0_u128; m]; let mut h = 0_u128; for i in 0..m { h *= b_base; h %= H; h += diff_a2[i]; h %= H; forward_hash[i] = h; } // backward hash let mut backward_hash = vec![0_u128; m]; h = 0; for i in (0..m).rev() { h *= b_base; h %= H; h += diff_a2[i]; h %= H; backward_hash[i] = h; } let mut pow_b = vec![0_u128; n]; let mut cur = 1_u128; for i in 0..n { pow_b[i] = cur; cur *= b_base; cur %= H; } let solve = |forward_hash: &Vec, backward_hash: &Vec, pow_b: &Vec, i: usize, l: usize| -> bool { let b = (backward_hash[i - l] + H - ((backward_hash[i] * pow_b[l]) % H)) % H; let f = (forward_hash[i + l] + H - ((forward_hash[i] * pow_b[l]) % H)) % H; b == f }; // 奇数長回文 for i in 0..m { let left = i; let right = m - 1 - i; let max_length = left.min(right); let mut low = 0_usize; let mut high = max_length; while high > low + 1 { let mid = (high + low) / 2; if solve(&forward_hash, &backward_hash, &pow_b, i, mid) { low = mid; } else { high = mid; } } if solve(&forward_hash, &backward_hash, &pow_b, i, high) { answer += 1 + high as u128; } else { answer += 1 + low as u128; } } let solve2 = |forward_hash: &Vec, backward_hash: &Vec, pow_b: &Vec, i: usize, l: usize| -> bool { let b = (backward_hash[i - l] + H - ((backward_hash[i + 1] * pow_b[l]) % H)) % H; let f = (forward_hash[i + 1 + l] + H - ((forward_hash[i] * pow_b[l]) % H)) % H; b == f }; // 偶数長回文 if m >= 2 { for i in 0..m - 1 { if diff_a2[i] != diff_a2[i + 1] { continue; } let left = i; let right = m - 1 - (i + 1); let max_length = left.min(right); let mut low = 0_usize; let mut high = max_length; while high > low + 1 { let mid = (high + low) / 2; if solve2(&forward_hash, &backward_hash, &pow_b, i, mid) { low = mid; } else { high = mid; } } if solve2(&forward_hash, &backward_hash, &pow_b, i, high) { answer += 1 + high as u128; } else { answer += 1 + low as u128; } } } println!("{}", answer); }