Isosceles Triangles
Difficulty: Hard

[Sevenkplus](http://sevenkplus.com/) has a regular polygon. Each vertex of the polygon has a color, either white or black. Sevenkplus wants to count the number of isosceles triangles whose vertices are vertices of the regular polygon and have the same color.  

**Input Format**   
The first line contains an integer T. T testcases follow.   
For each test case, there is only one line, which consists of a 01-string with length >= 3. Number of vertices `n` of the regular polygon equals length of the string. The string represents color of vertices in clockwise order. `0` represents white and `1` represents black. 

**Output Format**  
For each test case, output one line in the format `Case #t: ans`, where `t` is the case number (starting from 1), and `ans` is the answer. 

**Constraints**  
Sum of all n in the input <= 10^6.  

**Sample Input**

	5
	001
	0001
	10001
	111010
	1101010

**Sample Output**

	Case 1: 0
	Case 2: 1
	Case 3: 1
	Case 4: 2
	Case 5: 3

**Explanation**

In case 5, indices of vertices of the three monochromatic isosceles triangles are (0,3,5), (1,3,5) and (2,4,6) (assuming indices start from 0). 

**Timelimits**  
Timelimits for this challenge is given [here](https://www.hackerrank.com/environment)

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:

Editorial: Isosceles Triangles - 101 Hack February Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><a href="https://www.hackerrank.com/contests/101feb14/challenges/isosceles-triangles">Isosceles Triangles</a>  </p>

<p><strong>Difficulty</strong> : Medium-Hard <br>
<strong>Required Knowledge</strong> : Bichromatic Isosceles Triangles <br>
<strong>Problem Setter</strong> : <a href="https://www.hackerrank.com/sevenkplus">Yuzhou Gu</a> <br>
<strong>Problem Tester</strong> : <a href="https://www.hackerrank.com/dsoboliev">Dmytro Soboliev</a>  </p>

<p><strong>Approach</strong>  </p>

<pre><code># of monochromatic isosceles triangl = # of triangle - # of bichromatic isosceles triangle
</code></pre>

<p>Each bichromatic isosceles triangle has two bichromatic edges, so we only need to count # of bichromatic edges. </p>

<p>Consider a pair (i,j) of vertices with different colors. 
Then its contribution to number of bichromatic edges in isosceles triangles is determined by distance between the vertices. 
With some analysis we find that this is easy to calculate. </p>

<pre>when n is odd and n%3 != 0: 
  each pair is in 3 iso tri
when n is odd and n%3 == 0: 
  each pair, except for O(n) pairs, is in 3 iso tri
when n is even and n%3 != 0:
  each pair, except for O(n) of them, 
     if dis is even, is in 4 iso tri
     if dis is odd, is in 2 iso tri
when n is even and n%3 == 0:
  each pair, except for O(n) of them, 
     if dis is even, is in 4 iso tri
     if dis is odd, is in 2 iso tri

</pre>

<p><strong>Setter's Solution</strong>  </p>

<pre><code>#include &lt;cstdio&gt;
#include &lt;cstring&gt;
#include &lt;cmath&gt;
#include &lt;cassert&gt;
#include &lt;ctime&gt;
#include &lt;set&gt;
#include &lt;map&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;numeric&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;

typedef long long ll;
typedef pair&lt;int, int&gt; PII;

#define fi first
#define se second
#define mp make_pair
#define pb push_back

#define N 1000010
char a[N]; int n;

ll ff() {
    ll S = 0;
    if (n&amp;1) {
        S = (ll)n*(n-1)/2;
        if (n%3 == 0) S -= n/3*2;
    } else {
        S = (ll)n*(n/2-1);
        if (n%3 == 0) S -= n/3*2;
    }
    return S;
}

ll gg() {
    ll S = 0;
    if (n&amp;1) {
        int S0 = 0, S1 = 0;
        for (int i = 0; i &lt; n; i ++)
            if (a[i] == '0') S0 ++;
            else S1 ++;
        S = (ll) S0*S1*6;
        if (n%3 == 0) {
            int n1 = n/3, n2 = n1*2;
            for (int i = 0; i &lt; n; i ++) {
                if (a[i] != a[(i+n1)%n]) S -= 2;
                if (a[i] != a[(i+n2)%n]) S -= 2;
            }
        }
    } else {
        int S00 = 0, S01 = 0, S10 = 0, S11 = 0;
        for (int i = 0; i &lt; n; i += 2)
            if (a[i] == '0') S00 ++;
            else S01 ++;
        for (int i = 1; i &lt; n; i += 2)
            if (a[i] == '0') S10 ++;
            else S11 ++;
        S += (ll)S00*S01*8;
        S += (ll)S10*S11*8;
        S += (ll)S00*S11*4;
        S += (ll)S10*S01*4;
        int n1 = n/2;
        for (int i = 0; i &lt; n; i ++)
            if (a[i] != a[(i+n1)%n]) S -= 2;
        if (n%3 == 0) {
            int n1 = n/3, n2 = n1*2;
            for (int i = 0; i &lt; n; i ++) {
                if (a[i] != a[(i+n1)%n]) S -= 2;
                if (a[i] != a[(i+n2)%n]) S -= 2;
            }
        }
    }
    return S/2;
}

int main() {
    int __; scanf("%d", &amp;__);
    int _ = 0;
    while (scanf("%s", a) != EOF) {
        _ ++;
        n = strlen(a);
        cout &lt;&lt; "Case " &lt;&lt; _ &lt;&lt; ": " &lt;&lt; ff()-gg()/2 &lt;&lt; endl;
    }
    return 0;
}
</code></pre>

<p><strong>Tester's Solution</strong>  </p>

<pre><code>#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;cmath&gt;
#include &lt;cstring&gt;
#include &lt;string&gt;
#include &lt;ctime&gt;
#include &lt;complex&gt;
#pragma comment (linker, "/STACK:256000000")

using namespace std;

struct base {
    double x, y;
    base() { x = y = 0;}
    base(int x_) { x = x_, y = 0;}
    base(double x_) { x = x_, y = 0;}
    base(double x, double y): x(x), y(y) {}
    double imag() const { return y;}
    double real() const { return x;}
    void imag(double value) { y = value;}
    void real(double value) { x = value;}
    base&amp; operator *= (const base&amp; other) { return *this = base(x * other.x - y * other.y, y * other.x + x * other.y);}
    base&amp; operator /= (double value) { return *this = base(x / value, y / value);}
    base&amp; operator += (const base&amp; other) { return *this = base(x + other.x, y + other.y);}
    base&amp; operator -= (const base&amp; other) { return *this = base(x - other.x, y - other.y);}
};
base operator * (const base&amp; a, const base&amp; b) { return base(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y);}
base operator * (const base&amp; a, double value) { return base(a.x * value, a.y * value);}
base operator + (const base&amp; a, const base&amp; b) { return base(a.x + b.x, a.y + b.y);}
base operator - (const base&amp; a, const base&amp; b) { return base(a.x - b.x, a.y - b.y);}
base operator / (const base&amp; a, double value) { return base(a.x / value, a.y / value);}

const double pi = 2 * acos(0.);
const int maxC = 4500000;
int rev[maxC];
base na[maxC], nb[maxC];

void shuffle(base* data, int n) {
    for (int i = 0; i &lt; n; ++i) {
        if (i &lt; rev[i]) {
            swap(data[i], data[rev[i]]);
        }
    }
}

void Step(base* data, int N) {
    if (N == 1) return;
    Step(data, N / 2);
    Step(data + N / 2, N / 2);
    base w(cos(2. * pi / N), sin(2. * pi / N));
    base cur(1), buf;
    for (int i = 0; i &lt; N / 2; ++i, cur *= w) {
        buf = cur * data[i + N / 2];
        data[i + N / 2] = data[i] - buf;
        data[i] += buf;
    }
}

void multiply(int a[], int n, int b[], int m, long long res[], int&amp; len) {
    int q = n + m;
    int sz = 1;
    while (sz &lt; q) sz *= 2;
    for (int i = 0; i &lt; n; ++i) na[i].x = a[i];
    for (int i = 0; i &lt; m; ++i) na[i].y = b[i];
    for (int i = n; i &lt; sz; ++i) na[i].x = 0.0;
    for (int i = m; i &lt; sz; ++i) na[i].y = 0.0;
    for (int i = 0; i &lt; sz; ++i) nb[i] = 0;
    int bits = 0;
    while ((1 &lt;&lt; bits) &lt; sz) ++bits;
    for (int i = 0; i &lt; sz; ++i) {
        *(rev + i) = 0;
        for (int j = 0; j &lt; bits; ++j) {
            if (i &amp; (1 &lt;&lt; j)) {
                *(rev + i) += 1 &lt;&lt; (bits - j - 1);
            }
        }
    }
    int index = 0;
    for (int i = 0;;++i) if ((1 &lt;&lt; i) == sz) { index = i; break;}
    shuffle(na, sz);
    Step(na, sz);

    nb[0] = na[0].x * na[0].y;
    for (int i = 1; i &lt; sz; ++i) {
        base buf1 = na[i], buf2 = base(na[sz - i].x, -na[sz - i].y);
        base tx = (buf1 + buf2) / 2.;
        base ty = base(0, -1) * (buf1 - buf2) / 2.;
        nb[i] = tx * ty;
    }
    shuffle(nb, sz);

    Step(nb, sz);
    reverse(nb + 1, nb + sz);
    for (int i = 0; i &lt; sz; ++i) {
        nb[i] /= (double)(sz);
    }
    for (int i = 0; i &lt; sz; ++i) {
        res[i] = (long long)(nb[i].real() + 0.5);
    }

    len = sz;
    while (len &gt; 1 &amp;&amp; res[len - 1] == 0) --len;
}

const int maxL = 1100000;
int c[maxL];
long long res[4 * maxL];
long long resO[4 * maxL];
int ps[maxL];

void buildResO(int c[], int n) {
    for (int i = 0; i &lt; 4 * n; ++i) {
        resO[i] = 0;
    }

    for (int i = 0; i &lt; 2 * n; ++i) {
        resO[i] = res[i];
    }

    for (int i = 0; i + 1 &lt; 2 * n; ++i) {
        if (i &lt; n) {
            resO[i] += (i + 1);
        } else {
            resO[i] += 2 * n - 1 - i;
        }
    }

    for (int i = 0; i &lt; n; ++i) {
        ps[i] = c[i];
        if (i &gt; 0) {
            ps[i] += ps[i - 1];
        }
    }

    for (int i = 0; i &lt; n; ++i) {
        resO[i] -= 2 * ps[i];
    }

    int current = ps[n - 1];
    for (int i = n; i + 1 &lt; 2 * n; ++i) {
        current -= c[i - n];
        resO[i] -= 2 * current;
    }

    for (int i = n + n - 1; i &gt;= 0; --i) {
        resO[i + n] += resO[i];
    }
}

long long getAnswer(int c[], int n) {
    int m;
    for (int i = 0; i &lt; 4 * n; ++i) {
        res[i] = 0;
    }
    multiply(c, n, c, n, res, m);
    buildResO(c, n);

    for (int i = n + n - 1; i &gt;= 0; --i) {
        res[i + n] += res[i];
    }

    long long ways = 0LL;
    for (int i = 0; i &lt; n; ++i) {
        if (c[i] == 1) {
            ways += (res[2 * i] + res[2 * (i + n)] - 1LL) / 2LL;
        } else {
            ways += (resO[2 * i] + resO[2 * (i + n)] - 1LL) / 2LL;
        }
    }

    if (n % 3 == 0) {
        for (int i = 0; i &lt; n / 3; ++i) {
            if (c[i] == 1 &amp;&amp; c[i + n / 3] == 1 &amp;&amp; c[i + 2 * n / 3] == 1) {
                ways -= 2LL;
            }
            if (c[i] == 0 &amp;&amp; c[i + n / 3] == 0 &amp;&amp; c[i + 2 * n / 3] == 0) {
                ways -= 2LL;
            }
        }
    }

    return ways;
}

char colors[maxL];

void solve(int test) {
    scanf("%s", &amp;colors);
    int n = strlen(colors);
    for (int i = 0; i &lt; n; ++i) {
        c[i] = colors[i] - '0';
    }
    printf("Case %d: %lld\n", test, getAnswer(c, n));
    for (int i = 0; i &lt; n; ++i) {
        colors[i] = 0;
    }
}

int main() {
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    int tests;
    scanf("%d\n", &amp;tests);
    for (int i = 0; i &lt; tests; ++i) {
        solve(i + 1);
        //cerr &lt;&lt; (i + 1) &lt;&lt; ": " &lt;&lt; clock() &lt;&lt; endl;
    }
    return 0;
}
</code></pre>

Reference solution (C++):
###C++  
```cpp  

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <ctime>
#include <complex>
#pragma comment (linker, "/STACK:256000000")
    
using namespace std;
    
struct base {
    double x, y;
    base() { x = y = 0;}
    base(int x_) { x = x_, y = 0;}
    base(double x_) { x = x_, y = 0;}
    base(double x, double y): x(x), y(y) {}
    double imag() const { return y;}
    double real() const { return x;}
    void imag(double value) { y = value;}
    void real(double value) { x = value;}
    base& operator *= (const base& other) { return *this = base(x * other.x - y * other.y, y * other.x + x * other.y);}
    base& operator /= (double value) { return *this = base(x / value, y / value);}
    base& operator += (const base& other) { return *this = base(x + other.x, y + other.y);}
    base& operator -= (const base& other) { return *this = base(x - other.x, y - other.y);}
};
base operator * (const base& a, const base& b) { return base(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y);}
base operator * (const base& a, double value) { return base(a.x * value, a.y * value);}
base operator + (const base& a, const base& b) { return base(a.x + b.x, a.y + b.y);}
base operator - (const base& a, const base& b) { return base(a.x - b.x, a.y - b.y);}
base operator / (const base& a, double value) { return base(a.x / value, a.y / value);}
    
const double pi = 2 * acos(0.);
const int maxC = 4500000;
int rev[maxC];
base na[maxC], nb[maxC];
    
void shuffle(base* data, int n) {
    for (int i = 0; i < n; ++i) {
        if (i < rev[i]) {
            swap(data[i], data[rev[i]]);
        }
    }
}
    
void Step(base* data, int N) {
    if (N == 1) return;
    Step(data, N / 2);
    Step(data + N / 2, N / 2);
    base w(cos(2. * pi / N), sin(2. * pi / N));
    base cur(1), buf;
    for (int i = 0; i < N / 2; ++i, cur *= w) {
        buf = cur * data[i + N / 2];
        data[i + N / 2] = data[i] - buf;
        data[i] += buf;
    }
}
    
void multiply(int a[], int n, int b[], int m, long long res[], int& len) {
    int q = n + m;
    int sz = 1;
    while (sz < q) sz *= 2;
    for (int i = 0; i < n; ++i) na[i].x = a[i];
    for (int i = 0; i < m; ++i) na[i].y = b[i];
    for (int i = n; i < sz; ++i) na[i].x = 0.0;
    for (int i = m; i < sz; ++i) na[i].y = 0.0;
    for (int i = 0; i < sz; ++i) nb[i] = 0;
    int bits = 0;
    while ((1 << bits) < sz) ++bits;
    for (int i = 0; i < sz; ++i) {
        *(rev + i) = 0;
        for (int j = 0; j < bits; ++j) {
            if (i & (1 << j)) {
                *(rev + i) += 1 << (bits - j - 1);
            }
        }
    }
    int index = 0;
    for (int i = 0;;++i) if ((1 << i) == sz) { index = i; break;}
    shuffle(na, sz);
    Step(na, sz);
    
    nb[0] = na[0].x * na[0].y;
    for (int i = 1; i < sz; ++i) {
        base buf1 = na[i], buf2 = base(na[sz - i].x, -na[sz - i].y);
        base tx = (buf1 + buf2) / 2.;
        base ty = base(0, -1) * (buf1 - buf2) / 2.;
        nb[i] = tx * ty;
    }
    shuffle(nb, sz);
    
    Step(nb, sz);
    reverse(nb + 1, nb + sz);
    for (int i = 0; i < sz; ++i) {
        nb[i] /= (double)(sz);
    }
    for (int i = 0; i < sz; ++i) {
        res[i] = (long long)(nb[i].real() + 0.5);
    }
    
    len = sz;
    while (len > 1 && res[len - 1] == 0) --len;
}
    
const int maxL = 1100000;
int c[maxL];
long long res[4 * maxL];
long long resO[4 * maxL];
int ps[maxL];
    
void buildResO(int c[], int n) {
    for (int i = 0; i < 4 * n; ++i) {
        resO[i] = 0;
    }
    
    for (int i = 0; i < 2 * n; ++i) {
        resO[i] = res[i];
    }
    
    for (int i = 0; i + 1 < 2 * n; ++i) {
        if (i < n) {
            resO[i] += (i + 1);
        } else {
            resO[i] += 2 * n - 1 - i;
        }
    }
    
    for (int i = 0; i < n; ++i) {
        ps[i] = c[i];
        if (i > 0) {
            ps[i] += ps[i - 1];
        }
    }
    
    for (int i = 0; i < n; ++i) {
        resO[i] -= 2 * ps[i];
    }
    
    int current = ps[n - 1];
    for (int i = n; i + 1 < 2 * n; ++i) {
        current -= c[i - n];
        resO[i] -= 2 * current;
    }
    
    for (int i = n + n - 1; i >= 0; --i) {
        resO[i + n] += resO[i];
    }
}
    
long long getAnswer(int c[], int n) {
    int m;
    for (int i = 0; i < 4 * n; ++i) {
        res[i] = 0;
    }
    multiply(c, n, c, n, res, m);
    buildResO(c, n);
    
    for (int i = n + n - 1; i >= 0; --i) {
        res[i + n] += res[i];
    }
    
    long long ways = 0LL;
    for (int i = 0; i < n; ++i) {
        if (c[i] == 1) {
            ways += (res[2 * i] + res[2 * (i + n)] - 1LL) / 2LL;
        } else {
            ways += (resO[2 * i] + resO[2 * (i + n)] - 1LL) / 2LL;
        }
    }
    
    if (n % 3 == 0) {
        for (int i = 0; i < n / 3; ++i) {
            if (c[i] == 1 && c[i + n / 3] == 1 && c[i + 2 * n / 3] == 1) {
                ways -= 2LL;
            }
            if (c[i] == 0 && c[i + n / 3] == 0 && c[i + 2 * n / 3] == 0) {
                ways -= 2LL;
            }
        }
    }
    
    return ways;
}
    
char colors[maxL];
    
void solve(int test) {
    scanf("%s", &colors);
    int n = strlen(colors);
    for (int i = 0; i < n; ++i) {
        c[i] = colors[i] - '0';
    }
    printf("Case %d: %lld\n", test, getAnswer(c, n));
    for (int i = 0; i < n; ++i) {
        colors[i] = 0;
    }
}
    
int main() {
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    
    int tests;
    scanf("%d\n", &tests);
    for (int i = 0; i < tests; ++i) {
        solve(i + 1);
        //cerr << (i + 1) << ": " << clock() << endl;
    }
    return 0;
}
```