Challenge: Fun With Series

Subdomeniu: Algebra (algebra)

Scor cont: 75.0 / 75

Submission status: Accepted

Submission score: 1.0

Submission ID: 464779714

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/fun-with-series/problem

Cerinta

Julia found a series, $G$, defined as:
$$G_n = \begin{cases}0 &n = 0\\1 &n = 1\\a\times G_{n-1}+b\times G_{n-2} & n\gt 1 \text{ and } a, b \ge 1 \end{cases}$$

For some integer $p$ (where $p \gt 0$), she finds $p + 2$ integers, $c_0,\  c_1,\ c_2, \ldots,\ c_{p+1}$, such that $L(p, n) = 0$ holds for all integers $n$ (where $n \gt p$):
$$L(p,\ n) = \sum_{i = 0}^{p + 1} c_i \left(G_{n-i}\right)^p$$

She realized that the values of $c_i$ are not unique, so she only considers the tuple $(c_0,\ c_1, \ldots,\ c_{p+1})$ such that $c_0 \gt 0$ and $c_0$ is minimal. It is guaranteed that when $c_0 \gt 0$ and $c_0$ is minimal, there exists only one tuple $(c_0,\ c_1, \ldots,\ c_{p+1})$.

Next, she defines $S_1(p)$ and $S_2(p)$: 
$$S_1(p) = \left( \sum c_i \right) \% (10^9+7)\ \ \ \ \ \forall c_i > 0$$
$$S_2(p) = \left( \sum \left|c_i \right| \right) \% (10^9+7)\ \ \ \ \forall c_i < 0$$

She then finds the following interesting property of $c_i$:
$$\prod_{i=0}^{p+1} \left|c_i\right| = w \times \prod_{i=2}^{p+1}  G_i^{z_i}$$

where $w$ and $z_i$ are integers such that:

* $w \ne 0$
* $z_{2} + 2p = z_{p + 1} + 2$
* $\sum\limits_{i=2}^{p+1} z_i = p$
    
Julia wants you to answer $q$ queries in the following forms:

1. `1 l r`: Using $S_1(p)$ and $S_2(p)$, print three space-separated integers denoting the respective values of $Count_1$, $Count_2$, and $Count_3$ where:

    * $Count_1$ is the total number of possible values of $p$ (where $l \le p \le r$) such that $S_1(p) \gt S_2(p)$.
    * $Count_2$ is the total number of possible values of $p$ (where $l \le p \le r$) such that $S_1(p) \lt S_2(p)$.
    * $Count_3$ is the total number of possible values of $p$ (where $l \le p \le r$) such that $S_1(p) = S_2(p)$.

2. `2 p u v`: Find the value of $S$ modulo $\left(10^9+7\right)$:
	$$S = \left(\prod_{i=u}^{v}G_i\right)^{\left(w + \phi\right)} \text{, where } \phi=\left|\sum_{i=u}^{v} z_i\right|$$

Input Format

The first line contains three space-separated integers describing the respective values of $a$, $b$, and $q$. 		
Each line $i$ of the $q$ subsequent lines contains three or four space-separated values denoting a query asked by Julia.

Output Format

Print $q$ lines of output where each line $i$ denotes the answer to query $i$.

Constraints

* $1 \le a,\ b \le 10^6$
* $1 \le q \le 5 \times 10^4$
* $1 \le l \le r \le 10^3$
* $1 \le p \le 10^6$
* $2 \le u \le v \le p + 1$

Cod sursa

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

static const long long MOD = 1000000007LL;

struct Query {
    int type;
    long long x, y, z; // type1: x=l, y=r; type2: x=p, y=u, z=v
};

static long long modPow(long long a, long long e, long long mod) {
    a %= mod;
    long long r = 1 % mod;
    while (e > 0) {
        if (e & 1) r = (__int128)r * a % mod;
        a = (__int128)a * a % mod;
        e >>= 1;
    }
    return r;
}

static long long modInv(long long a) {
    return modPow(a, MOD - 2, MOD);
}

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

    long long a, b;
    int q;
    cin >> a >> b >> q;

    vector<Query> queries;
    queries.reserve(q);

    int maxR = 0;
    int maxP = 0;
    int maxV = 1;

    for (int i = 0; i < q; i++) {
        int t;
        cin >> t;
        if (t == 1) {
            long long l, r;
            cin >> l >> r;
            queries.push_back({t, l, r, 0});
            maxR = max<long long>(maxR, r);
        } else {
            long long p, u, v;
            cin >> p >> u >> v;
            queries.push_back({t, p, u, v});
            maxP = max<long long>(maxP, p);
            maxV = max<long long>(maxV, v);
        }
    }

    int N = maxR + 1;
    N = max(N, 1);

    int G = max(maxV, N + 2);

    vector<int> g(G + 1, 0);
    g[0] = 0;
    g[1] = 1;
    for (int i = 2; i <= G; i++) {
        long long val = ((__int128)(a % MOD) * g[i - 1] + (__int128)(b % MOD) * g[i - 2]) % MOD;
        g[i] = (int)val;
    }

    vector<long long> prefProd(G + 1, 1);
    for (int i = 1; i <= G; i++) {
        prefProd[i] = (prefProd[i - 1] * g[i]) % MOD;
    }

    vector<vector<int>> tria(N + 2, vector<int>(N + 2, 0));

    if (N >= 1) {
        tria[1][0] = 1;
        tria[1][1] = 1;
    }

    for (int i = 2; i <= N; i++) {
        tria[i][0] = 1;
        long long rpow = 1;
        for (int j = 1; j <= i; j++) {
            long long term1 = ((__int128)tria[i - 1][j - 1] * g[i - j + 1]) % MOD;
            term1 = (term1 * rpow) % MOD;

            long long term2 = ((__int128)tria[i - 1][j] * g[j - 1]) % MOD;
            term2 = (term2 * (b % MOD)) % MOD;

            tria[i][j] = (int)((term1 + term2) % MOD);

            rpow = (rpow * (b % MOD)) % MOD;
        }
    }

    vector<int> pref0(N + 2, 0), pref1(N + 2, 0), pref2(N + 2, 0);

    auto isSn = [](int j) -> bool {
        int m = j & 3;
        return (m == 1 || m == 2);
    };

    for (int i = 1; i <= N; i++) {
        int sp = 0, sn = 0;
        for (int j = 0; j <= i; j++) {
            if (isSn(j)) {
                sn += tria[i][j];
                if (sn >= MOD) sn -= MOD;
            } else {
                sp += tria[i][j];
                if (sp >= MOD) sp -= MOD;
            }
        }
        pref0[i] = pref0[i - 1];
        pref1[i] = pref1[i - 1];
        pref2[i] = pref2[i - 1];

        if (sn == sp) pref1[i]++;
        else if (sn > sp) pref2[i]++;
        else pref0[i]++;
    }

    for (auto &qq : queries) {
        if (qq.type == 1) {
            int L = (int)qq.x + 1;
            int R = (int)qq.y + 1;
            L = max(L, 1);
            R = min(R, N);

            int ans0 = pref0[R] - pref0[L - 1];
            int ans2 = pref2[R] - pref2[L - 1];
            int ans1 = pref1[R] - pref1[L - 1];

            cout << ans0 << " " << ans2 << " " << ans1 << "\n";
        } else {
            long long p = qq.x;
            int u = (int)qq.y;
            int v = (int)qq.z;

            long long prod_uv = prefProd[v] * modInv(prefProd[u - 1]) % MOD;

            long long wp = p * (p + 1) * (p + 2) / 6;

            long long w = modPow((b % (MOD - 1) + (MOD - 1)) % (MOD - 1), wp, MOD - 1);

            long long phi = 1LL * v * (v - 1) - 1LL * (u - 1) * (u - 2) - 1LL * p * (v - u + 1);
            phi = llabs(phi);
            phi = (phi + w) % (MOD - 1);

            cout << modPow(prod_uv, phi, MOD) << "\n";
        }
    }

    return 0;
}
HackerRank Algebra – Fun With Series