Challenge: Isosceles Triangles

Scor cont: 250.0 / 250

Submission status: Accepted

Submission score: 1.0

Submission ID: 464816213

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/isosceles-triangles/problem

Cerinta

[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)

Cod sursa

#include <bits/stdc++.h>
using namespace std;

using cd = complex<double>;
const double PI = acos(-1.0);

static void fft(vector<cd>& a, bool invert) {
    int n = (int)a.size();
    for (int i = 1, j = 0; i < n; i++) {
        int bit = n >> 1;
        for (; j & bit; bit >>= 1) j ^= bit;
        j ^= bit;
        if (i < j) swap(a[i], a[j]);
    }
    for (int len = 2; len <= n; len <<= 1) {
        double ang = 2 * PI / len * (invert ? -1 : 1);
        cd wlen(cos(ang), sin(ang));
        for (int i = 0; i < n; i += len) {
            cd w(1);
            for (int j = 0; j < len / 2; j++) {
                cd u = a[i + j];
                cd v = a[i + j + len / 2] * w;
                a[i + j] = u + v;
                a[i + j + len / 2] = u - v;
                w *= wlen;
            }
        }
    }
    if (invert) {
        for (cd& x : a) x /= n;
    }
}

static vector<long long> convolution01(const vector<int>& a, const vector<int>& b) {
    int need = (int)a.size() + (int)b.size() - 1;
    int n = 1;
    while (n < need) n <<= 1;

    vector<cd> fa(n), fb(n);
    for (int i = 0; i < (int)a.size(); i++) fa[i] = cd(a[i], 0);
    for (int i = 0; i < (int)b.size(); i++) fb[i] = cd(b[i], 0);

    fft(fa, false);
    fft(fb, false);
    for (int i = 0; i < n; i++) fa[i] *= fb[i];
    fft(fa, true);

    vector<long long> res(need);
    for (int i = 0; i < need; i++) res[i] = llround(fa[i].real());
    return res;
}

static long long apexCount(const vector<int>& col) {
    int n = (int)col.size();
    vector<long long> conv = convolution01(col, col); // linear by index sum

    vector<long long> pairCnt(n, 0);

    auto diagCount = [&](int s) -> long long {
        if (n & 1) {
            // inverse of 2 modulo odd n
            int inv2 = (n + 1) / 2;
            int u = (int)((1LL * s * inv2) % n);
            return col[u];
        } else {
            if (s & 1) return 0;
            int u1 = (s / 2) % n;
            int u2 = (u1 + n / 2) % n;
            return col[u1] + col[u2];
        }
    };

    for (int s = 0; s < n; s++) {
        long long ordered = conv[s];
        if (s + n < (int)conv.size()) ordered += conv[s + n];
        long long diag = diagCount(s);
        pairCnt[s] = (ordered - diag) / 2;
    }

    long long apex = 0;
    for (int i = 0; i < n; i++) {
        if (!col[i]) continue;
        int s = (2LL * i) % n;
        apex += pairCnt[s];
    }
    return apex;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
        string s;
        cin >> s;
        int n = (int)s.size();

        vector<int> black(n), white(n);
        for (int i = 0; i < n; i++) {
            black[i] = (s[i] == '1');
            white[i] = 1 - black[i];
        }

        long long apex = apexCount(black) + apexCount(white);

        long long equi = 0;
        if (n % 3 == 0) {
            int step = n / 3;
            for (int i = 0; i < step; i++) {
                if (s[i] == s[i + step] && s[i] == s[i + 2 * step]) equi++;
            }
        }

        long long ans = apex - 2 * equi;
        cout << "Case " << tc << ": " << ans << '\n';
    }
    return 0;
}
HackerRank Geometry – Isosceles Triangles