Problem:
Score : 400 points

Problem Statement

We have a string S of length N consisting of R, G, and B.

Find the number of triples (i,~j,~k)~(1 \leq i < j < k \leq N) that satisfy both of the following conditions:

S_i \neq S_j, S_i \neq S_k, and S_j \neq S_k.

j - i \neq k - j.

Constraints

1 \leq N \leq 4000

S is a string of length N consisting of R, G, and B.

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the number of triplets in question.

Sample Input 1

4
RRGB

Sample Output 1

1

Only the triplet (1,~3,~4) satisfies both conditions. The triplet (2,~3,~4) satisfies the first condition but not the second, so it does not count.

Sample Input 2

39
RBRBGRBGGBBRRGBBRRRBGGBRBGBRBGBRBBBGBBB

Sample Output 2

1800

Solution in Kotlin (1.3.71) (judge verdict: Wrong Answer)

import java.io.*
import java.lang.*
import java.util.*

// Constant
val sc = FastScanner()
val pw = PrintWriter(System.out)
const val MOD = 1000000007L
const val INF = 2147483647
const val LINF = 9223372036854775807L

fun main(args: Array<String>) {
    solve()
    pw.flush()
}


fun solve() {
    val n = nextInt()
    val s = next()
    val red = intAry(n + 1)
    val green = intAry(n + 1)
    val blue = intAry(n + 1)
    for (i in n - 1 downTo 0){
        red[i] = red[i + 1]
        green[i] = green[i + 1]
        blue[i] = blue[i + 1]
        when(s[i]){
            'R' -> red[i] += 1
            'G' -> green[i] += 1
            'B' -> blue[i] += 1
        }
    }

    var ans = 0
    for (i in 0 until n - 2){
        for (j in i + 1 until n - 1){
            if(s[i] == s[j]) continue
            val gap = j - i
            when{
                (s[i] == 'R' && s[j] == 'G') || (s[i] == 'G' && s[j] == 'R') -> {
                    var tmp = blue[j]
                    if(j + gap < n && s[j + gap] == 'B') tmp--
                    ans += tmp
                }
                (s[i] == 'R' && s[j] == 'B') || (s[i] == 'B' && s[j] == 'R') -> {
                    var tmp = green[j]
                    if(j + gap < n && s[j + gap] == 'G') tmp--
                    ans += tmp
                }
                (s[i] == 'G' && s[j] == 'B') || (s[i] == 'B' && s[j] == 'G') -> {
                    var tmp = red[j]
                    if(j + gap < n && s[j + gap] == 'R') tmp--
                    ans += tmp
                }
            }

        }
    }

    println(ans)

}




// Output
fun println(v: String) {
    pw.println(v)
}
fun print(v: String) {
    pw.print(v)
}

// Input
fun next() = sc.next()
fun nextInt() = sc.nextInt()
fun nextLong() = sc.nextLong()
fun nextDouble() = next().toDouble()
fun nextAry(n: Int): Array<String> {
    val ary = ary(n)
    for (i in 0 until n) ary[i] = next()
    return ary
}
fun nextIntAry(n: Int): IntArray {
    val ary = intAry(n)
    for (i in 0 until n) ary[i] = nextInt()
    return ary
}
fun nextLongAry(n: Int): LongArray {
    val ary = longAry(n)
    for (i in 0 until n) ary[i] = nextLong()
    return ary
}
fun nextDoubleAry(n: Int): DoubleArray {
    val ary = doubleAry(n)
    for (i in 0 until n) ary[i] = nextDouble()
    return ary
}

// Statement
fun ary(n: Int, init: String = "") = Array(n) { init }
fun intAry(n: Int, init: Int = 0) = IntArray(n) { init }
fun longAry(n: Int, init: Long = 0L) = LongArray(n) { init }
fun doubleAry(n: Int, init: Double = 0.0) = DoubleArray(n) { init }
fun ary2(n: Int, m: Int, init: String = "") = Array(n) { Array(m) { init } }
fun intAry2(n: Int, m: Int, init: Int = 0) = Array(n) { IntArray(m) { init } }
fun longAry2(n: Int, m: Int, init: Long = 0) = Array(n) { LongArray(m) { init } }
fun doubleAry2(n: Int, m: Int, init: Double = 0.0) = Array(n) { DoubleArray(m) { init } }
fun ary3(n: Int, m: Int, k: Int, init: String = "") = Array(n) { Array(m) { Array(k) { init } } }
fun intAry3(n: Int, m: Int, k: Int, init: Int = 0) = Array(n) { Array(m) { IntArray(k) { init } } }
fun longAry3(n: Int, m: Int, k: Int, init: Long = 0L) = Array(n) { Array(m) { LongArray(k) { init } } }
fun doubleAry3(n: Int, m: Int, k: Int, init: Double = 0.0) = Array(n) { Array(m) { DoubleArray(k) { init } } }
fun list() = mutableListOf<String>()
fun intList() = mutableListOf<Int>()
fun longList() = mutableListOf<Long>()
fun doubleList() = mutableListOf<Double>()
fun strSet() = mutableSetOf<String>()
fun intSet() = mutableSetOf<Int>()
fun longSet() = mutableSetOf<Long>()
fun doubleSet() = mutableSetOf<Double>()
fun <E, V> map() = mutableMapOf<E, V>()

// Monoid
val addIntFunc = {a: Int, b: Int -> a + b}
val addLongFunc = {a: Long, b: Long -> a + b}
val mulIntFunc = {a: Int, b: Int -> a * b}
val mulLongFunc = {a: Long, b: Long -> a * b}
val maxIntFunc = {a: Int, b: Int -> max(a, b)}
val maxLongFunc = {a: Long, b: Long -> max(a, b)}
val minIntFunc = {a: Int, b: Int -> min(a, b)}
val minLongFunc = {a: Long, b: Long -> min(a, b)}
val gcdIntFunc = {a: Int, b: Int -> gcd(a, b)}
val gcdLongFunc = {a: Long, b: Long -> gcd(a, b)}
val lcmIntFunc = {a: Int, b: Int -> lcm(a, b)}
val lcmLongFunc = {a: Long, b: Long -> lcm(a, b)}
val xorIntFunc = {a: Int, b: Int -> a xor b}
val xorLongFunc = {a: Long, b: Long -> a xor b}
fun calc(a: Int, b: Int, op: (Int, Int) -> Int) = op(a, b)
fun calc(a: Long, b: Long, op: (Long, Long) -> Long) = op(a, b)

// Extension
fun Int.a() = this.toLong()
fun Long.a() = this.toInt()
fun IntArray.lowerBound(n: Int): Int {
    var ok = this.size
    var ng = -1
    while (abs(ok - ng) > 1) {
        val mid = (ok + ng) / 2
        if (this[mid] >= n) ok = mid
        else ng = mid
    }
    return ok
}
fun LongArray.lowerBound(n: Long): Int {
    var ok = this.size
    var ng = -1
    while (abs(ok - ng) > 1) {
        val mid = (ok + ng) / 2
        if (this[mid] >= n) ok = mid
        else ng = mid
    }
    return ok
}
fun DoubleArray.lowerBound(n: Double): Int {
    var ok = this.size
    var ng = -1
    while (abs(ok - ng) > 1) {
        val mid = (ok + ng) / 2
        if (this[mid] >= n) ok = mid
        else ng = mid
    }
    return ok
}
fun MutableList<Int>.intLowerBound(n: Int): Int {
    var ok = this.size
    var ng = -1
    while (abs(ok - ng) > 1) {
        val mid = (ok + ng) / 2
        if (this[mid] >= n) ok = mid
        else ng = mid
    }
    return ok
}
fun MutableList<Long>.longLowerBound(n: Long): Int {
    var ok = this.size
    var ng = -1
    while (abs(ok - ng) > 1) {
        val mid = (ok + ng) / 2
        if (this[mid] >= n) ok = mid
        else ng = mid
    }
    return ok
}
fun MutableList<Double>.doubleLowerBound(n: Double): Int {
    var ok = this.size
    var ng = -1
    while (abs(ok - ng) > 1) {
        val mid = (ok + ng) / 2
        if (this[mid] >= n) ok = mid
        else ng = mid
    }
    return ok
}
fun IntArray.cumsum(op: (Int, Int) -> Int): IntArray {
    val s = intAry(this.size + 1)
    s[1] = this[0]
    for (i in 1 until this.size) s[i + 1] = calc(s[i], this[i], op)
    return s
}
fun LongArray.cumsum(op: (Long, Long) -> Long): LongArray {
    val s = longAry(this.size + 1)
    s[1] = this[0]
    for (i in 1 until this.size) s[i + 1] = calc(s[i], this[i], op)
    return s
}
fun MutableMap<String, Int>.counting(n: Int) {
    repeat(n) {
        val a = next()
        if (this.containsKey(a)) this[a] = this[a]!! + 1
        else this[a] = 1
    }
}
fun MutableMap<Int, Int>.intCounting(n: Int) {
    repeat(n) {
        val a = nextInt()
        if (this.containsKey(a)) this[a] = this[a]!! + 1
        else this[a] = 1
    }
}
fun MutableMap<Long, Int>.longCounting(n: Int) {
    repeat(n) {
        val a = nextLong()
        if (this.containsKey(a)) this[a] = this[a]!! + 1
        else this[a] = 1
    }
}

// Mathematics
fun abs(n: Int): Int = Math.abs(n)
fun abs(n: Long): Long = Math.abs(n)
fun abs(n: Double): Double = Math.abs(n)
fun max(vararg values: Int) = if (values.isEmpty()) -INF else values.max()!!
fun max(vararg values: Long) = if (values.isEmpty()) -LINF else values.max()!!
fun min(vararg values: Int) = if (values.isEmpty()) INF else values.min()!!
fun min(vararg values: Long) = if (values.isEmpty()) LINF else values.min()!!
tailrec fun gcd(a: Int, b: Int): Int = if (b == 0) a else if (a % b == 0) b else gcd(b, (a % b))
tailrec fun gcd(a: Long, b: Long): Long = if (b == 0L) a else if (a % b == 0L) b else gcd(b, (a % b))
fun lcm(a: Int, b: Int): Int = a / gcd(a, b) * b
fun lcm(a: Long, b: Long): Long = a / gcd(a, b) * b
fun modpow(a: Long, n: Long, p: Long = MOD): Long {
    var res = 1L
    var ar = a
    var nr = n
    while (nr > 0) {
        if ((nr and 1) == 1L) res = res * ar % p
        ar = ar * ar % p
        nr = nr shr 1
    }
    return res
}
fun modinv(a: Long, p: Long = MOD): Long = modpow(a, p - 2, p)
fun ncr(n: Long, r: Long): Long {
    var a = 1L
    var b = 1L
    for (i in 1..r) {
        a = a * (n + 1 - i) % MOD
        b = b * i % MOD
    }
    return modinv(b, MOD) * a % MOD
}

class Combination(private val max: Int) {
    private val fac = LongArray(max)
    private val finv = LongArray(max)
    private val inv = LongArray(max)
    private val p = MOD.a()
    fun init() {
        fac[0] = 1
        fac[1] = 1
        finv[0] = 1
        finv[1] = 1
        inv[1] = 1
        for (i in 2 until max) {
            fac[i] = fac[i - 1] * i % p
            inv[i] = p - inv[p % i] * (p / i) % p;
            finv[i] = finv[i - 1] * inv[i] % p
        }
    }

    fun com(n: Int, r: Int): Long = if (n < r || (n < 0 || r < 0)) 0 else fac[n] * (finv[r] * finv[n - r] % p) % p
}

class Permutation(private val n: Int, private var searched: Int = 0, private var nextIndex: Int = 0) {
    private val size = fact(n)
    private val permList = Array(size) { IntArray(n) { 0 } }

    private tailrec fun fact(n: Int, ans: Int = 1): Int {
        return if (n == 0) ans
        else fact(n - 1, ans * n)
    }

    fun init() {
        create(0, IntArray(n) { 0 }, Array<Boolean>(n) { false })
    }

    private fun create(num: Int, list: IntArray, flag: Array<Boolean>) {
        if (num == n) {
            permList[searched] = list.copyOf()
            searched++
        }
        for (i in 0 until n) {
            if (flag[i]) continue
            list[num] = i
            flag[i] = true
            create(num + 1, list, flag)
            flag[i] = false
        }
    }

    fun hasNext(): Boolean {
        return if (nextIndex < size) {
            true
        } else {
            nextIndex = 0
            false
        }
    }

    fun nextPerm(): IntArray = permList[nextIndex++]
}

// Graph
data class Node(val id: Int, var past: Int = -1, val edges: MutableList<Edge> = mutableListOf())
data class Edge(val from: Int, val to: Int, val cost: Long = 1L)

fun dfs(nodes: Array<Node>, now: Int, seen: Array<Boolean>) {
    seen[now] = true
    for (edge in nodes[now].edges) {
        if (seen[edge.to]) continue
        dfs(nodes, edge.to, seen)
    }
}

fun bfs(nodes: Array<Node>, start: Int): LongArray {
    val queue = ArrayDeque<Int>()
    queue.add(start)
    val dist = longAry(nodes.size, -1L)
    dist[start] = 0L
    while (queue.isNotEmpty()) {
        val now = queue.poll()
        for (edge in nodes[now].edges) {
            if (dist[edge.to] != -1L) continue
            dist[edge.to] = dist[now] + 1
            queue.add(edge.to)
        }
    }
    return dist
}

fun dijkstra(nodes: Array<Node>, start: Int): LongArray {
    val queue = PriorityQueue(16) { e1: Edge, e2: Edge ->
        return@PriorityQueue when {
            e1.cost < e2.cost -> -1
            e2.cost > e1.cost -> 1
            else -> 0
        }
    }
    queue.add(Edge(start, start, 0L))
    val dist = longAry(nodes.size, LINF / 2)
    dist[start] = 0
    while (queue.isNotEmpty()) {
        val now = queue.poll()
        if (dist[now.to] < now.cost) continue;
        for (edge in nodes[now.to].edges) {
            if (dist[edge.to] <= dist[edge.from] + edge.cost) continue
            dist[edge.to] = dist[edge.from] + edge.cost
            queue.add(Edge(edge.from, edge.to, dist[edge.to]))
            nodes[edge.to].past = edge.from
        }
    }
    return dist
}

class UnionFind(size: Int) {
    private val par = IntArray(size) { it }
    private val size = IntArray(size) { 1 }
    fun root(x: Int): Int {
        return if (par[x] == x) {
            x
        } else {
            par[x] = root(par[x])
            par[x]
        }
    }

    fun same(x: Int, y: Int): Boolean = root(x) == root(y)
    fun unite(x: Int, y: Int) {
        var a = root(x)
        var b = root(y)
        if (a == b) return
        if (size[a] < size[b]) {
            var tmp = a
            a = b
            b = tmp
        }
        size[a] += size[b]
        par[b] = a
    }

    fun size(x: Int): Int = size[root(x)]
}

class IntSegmentTree(
    private val a: IntArray,
    private val op: (Int, Int) -> Int,
    private val def: Int = 0,
    private val size: Int = a.size,
    private val n: Int = Integer.highestOneBit(size) shl 1
) {
    private val nodes = intAry(2 * n - 1, def)

    fun init() {
        for (i in 0 until size) nodes[i + n - 1] = a[i]
        for (i in n - 2 downTo 0) nodes[i] = calc(nodes[2 * i + 1], nodes[2 * i + 2], op)
    }

    fun update(x: Int, value: Int) {
        var index = x + n - 1
        nodes[index] = value
        while (index > 0) {
            index = (index - 1) / 2
            nodes[index] = calc(nodes[2 * index + 1], nodes[2 * index + 2], op)
        }
    }

    fun get(a: Int, b: Int) = getSub(a, b, 0, 0, n)
    fun getSub(a: Int, b: Int, k: Int, l: Int, r: Int): Int {
        return when {
            r <= a || b <= l -> def
            a <= l && r <= b -> nodes[k]
            else -> {
                val vl = getSub(a, b, k * 2 + 1, l, (l + r) / 2)
                val vr = getSub(a, b, k * 2 + 2, (l + r) / 2, r)
                calc(vl, vr, op)
            }
        }
    }

    fun joinToString(separator: String) = nodes.drop(n - 1).take(size).joinToString(separator)
}

class LongSegmentTree(
    private val a: LongArray,
    private val op: (Long, Long) -> Long,
    private val def: Long = 0,
    private val size: Int = a.size,
    private val n: Int = Integer.highestOneBit(size) shl 1
) {
    private val nodes = longAry(2 * n - 1, def)

    fun init() {
        for (i in 0 until size) nodes[i + n - 1] = a[i]
        for (i in n - 2 downTo 0) nodes[i] = calc(nodes[2 * i + 1], nodes[2 * i + 2], op)
    }

    fun update(x: Int, value: Long) {
        var index = x + n - 1
        nodes[index] = value
        while (index > 0) {
            index = (index - 1) / 2
            nodes[index] = calc(nodes[2 * index + 1], nodes[2 * index + 2], op)
        }
    }

    fun get(a: Int, b: Int) = getSub(a, b, 0, 0, n)
    fun getSub(a: Int, b: Int, k: Int, l: Int, r: Int): Long {
        return when {
            r <= a || b <= l -> def
            a <= l && r <= b -> nodes[k]
            else -> {
                val vl = getSub(a, b, k * 2 + 1, l, (l + r) / 2)
                val vr = getSub(a, b, k * 2 + 2, (l + r) / 2, r)
                calc(vl, vr, op)
            }
        }
    }

    fun joinToString(separator: String) = nodes.drop(n - 1).take(size).joinToString(separator)
}

// Scanner
class FastScanner {
    private val sin: InputStream = System.`in`
    private val buffer: ByteArray = ByteArray(1024) { 0 }
    private var ptr = 0
    private var buflen = 0

    private fun hasNextByte(): Boolean {
        return when {
            ptr < buflen -> true
            else -> {
                ptr = 0
                buflen = sin.read(buffer)
                if (buflen <= 0) false
                true
            }
        }
    }

    private fun readByte(): Int {
        return when {
            hasNextByte() -> buffer[ptr++].toInt()
            else -> -1
        }
    }

    private fun isPrintableChar(c: Int) = c in 33..126

    fun hasNext(): Boolean {
        while (hasNextByte() && !isPrintableChar(buffer[ptr].toInt())) ptr++
        return hasNextByte()
    }

    fun next(): String {
        if (!hasNext()) throw NoSuchElementException()
        val sb = StringBuilder()
        var b = readByte()
        while (isPrintableChar(b)) {
            sb.appendCodePoint(b)
            b = readByte()
        }
        return sb.toString()
    }

    fun nextLong(): Long {
        if (!hasNext()) throw NoSuchElementException()
        var n = 0L
        var minus = false
        var b = readByte()
        if (b.toChar() == '-') {
            minus = true
            b = readByte()
        }
        if (b.toChar() !in '0'..'9') throw NumberFormatException()
        while (true) {
            when {
                b.toChar() in '0'..'9' -> {
                    n *= 10
                    n += b.toChar() - '0'
                }
                b == -1 || !isPrintableChar(b) -> return if (minus) -n else n
                else -> throw NumberFormatException()
            }
            b = readByte()
        }
    }

    fun nextInt(): Int {
        val nl = nextLong()
        if (nl !in Int.MIN_VALUE..Int.MAX_VALUE) throw NumberFormatException()
        return nl.toInt()
    }
}