All Euler problems
Project Euler

Ascending Subsequences

Define a_i = 153^i mod 10,000,019 for i >= 1. An ascending subsequence of length 4 within the first n terms is a tuple (a_(i_1), a_(i_2), a_(i_3), a_(i_4)) with i_1 < i_2 < i_3 < i_4 and a_(i_1) <...

Source sync Apr 19, 2026
Problem #0733
Level Level 21
Solved By 571
Languages C++, Python
Answer 574368578
Length 267 words
modular_arithmeticlinear_algebrasequence

Problem Statement

This archive keeps the full statement, math, and original media on the page.

Let \(a_i\) be the sequence defined by \(a_i=153^i \bmod 10\,000\,019\) for \(i \ge 1\). The first terms of \(a_i\) are: \(153, 23409, 3581577, 7980255, 976697, 9434375, \dots \)

Consider the subsequences consisting of \(4\) terms in ascending order. For the part of the sequence shown above, these are:

\(153, 23409, 3581577, 7980255\)

\(153, 23409, 3581577, 9434375\)

\(153, 23409, 7980255, 9434375\)

\(153, 23409, 976697, 9434375\)

\(153, 3581577, 7980255, 9434375\) and

\(23409, 3581577, 7980255, 9434375\).

Define \(S(n)\) to be the sum of the terms for all such subsequences within the first \(n\) terms of \(a_i\). Thus \(S(6)=94513710\).

You are given that \(S(100)=4465488724217\).

Find \(S(10^6)\) modulo \(1\,000\,000\,007\).

Problem 733: Ascending Subsequences

Mathematical Analysis

Counting with Weighted Sums

For each ascending subsequence (ai1,ai2,ai3,ai4)(a_{i_1}, a_{i_2}, a_{i_3}, a_{i_4}), its contribution to SS is ai1+ai2+ai3+ai4a_{i_1} + a_{i_2} + a_{i_3} + a_{i_4}.

We can decompose: the contribution of aja_j at position kk (1st, 2nd, 3rd, or 4th element) equals aja_j times the number of ascending subsequences where aja_j occupies position kk.

BIT/Fenwick Tree Approach

Define arrays for j=1,,nj = 1, \ldots, n:

  • ck(j)c_k(j) = number of ascending subsequences of length kk ending at jj.
  • sk(j)s_k(j) = sum of all elements in all ascending subsequences of length kk ending at jj.

Recurrence:

ck(j)=i<jai<ajck1(i),sk(j)=i<jai<ajsk1(i)+ajck(j)c_k(j) = \sum_{\substack{i < j \\ a_i < a_j}} c_{k-1}(i), \quad s_k(j) = \sum_{\substack{i < j \\ a_i < a_j}} s_{k-1}(i) + a_j \cdot c_k(j)

These prefix sums over ai<aja_i < a_j can be computed efficiently using a Fenwick tree (BIT) indexed by the value aia_i (after coordinate compression).

Editorial

Sum of all elements in all ascending subsequences of length 4. Uses Fenwick trees for efficient prefix sum queries. We coordinate-compress the values to [1,n][1, n]. We then maintain 4 Fenwick trees for c1,c2,c3,c4c_1, c_2, c_3, c_4 (counts) and 4 for s1,s2,s3,s4s_1, s_2, s_3, s_4 (sums). Finally, process elements left to right. For each aja_j.

Pseudocode

Generate all $a_i$ for $i = 1, \ldots, n$
Coordinate-compress the values to $[1, n]$
Maintain 4 Fenwick trees for $c_1, c_2, c_3, c_4$ (counts) and 4 for $s_1, s_2, s_3, s_4$ (sums)
Process elements left to right. For each $a_j$:
Query prefix sum of $c_{k-1}$ and $s_{k-1}$ for values $< a_j$
Update $c_k$ and $s_k$ at position $a_j$
Final answer: $S = \sum_j s_4(j)$

Verification

nnS(n)S(n)
694,513,710
1004,465,488,724,217

Correctness

Theorem. The method described above computes exactly the quantity requested in the problem statement.

Proof. The preceding analysis identifies the admissible objects and derives the formula, recurrence, or exhaustive search carried out by the algorithm. The computation evaluates exactly that specification, so every valid contribution is included once and no invalid contribution is counted. Therefore the returned value is the required answer. \square

Complexity Analysis

  • Time: O(nlogn)O(n \log n) — four passes with Fenwick tree queries/updates.
  • Space: O(n)O(n) for the Fenwick trees.
  • For n=106n = 10^6: runs in seconds.

Answer

574368578\boxed{574368578}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_733/solution.cpp
#include <bits/stdc++.h>
using namespace std;

/*
 * Problem 733: Ascending Subsequences
 *
 * Sum of all elements in all length-4 ascending subsequences of a_i = 153^i mod 10000019.
 * Uses Fenwick trees for O(n log n) computation.
 */

const int MODP = 1000000007;
const int SEQ_MOD = 10000019;

struct BIT {
    int n;
    vector<long long> tree;
    BIT(int n) : n(n), tree(n + 1, 0) {}
    void update(int i, long long v) {
        for (; i <= n; i += i & -i) tree[i] = (tree[i] + v) % MODP;
    }
    long long query(int i) {
        long long s = 0;
        for (; i > 0; i -= i & -i) s = (s + tree[i]) % MODP;
        return s;
    }
};

int main() {
    int n = 1000000;
    vector<long long> a(n + 1);
    a[1] = 153;
    for (int i = 2; i <= n; i++) a[i] = a[i-1] * 153 % SEQ_MOD;

    // Coordinate compression
    vector<long long> sorted_a(a.begin() + 1, a.end());
    sort(sorted_a.begin(), sorted_a.end());
    sorted_a.erase(unique(sorted_a.begin(), sorted_a.end()), sorted_a.end());
    int sz = sorted_a.size();
    auto compress = [&](long long v) {
        return lower_bound(sorted_a.begin(), sorted_a.end(), v) - sorted_a.begin() + 1;
    };

    vector<BIT> cnt(5, BIT(sz)), sm(5, BIT(sz));
    long long total = 0;

    for (int j = 1; j <= n; j++) {
        int v = compress(a[j]);
        for (int k = 4; k >= 1; k--) {
            long long ck, sk;
            if (k == 1) {
                ck = 1;
                sk = a[j] % MODP;
            } else {
                ck = cnt[k-1].query(v - 1);
                sk = (sm[k-1].query(v - 1) + a[j] % MODP * ck) % MODP;
            }
            cnt[k].update(v, ck);
            sm[k].update(v, sk);
            if (k == 4) total = (total + sk) % MODP;
        }
    }

    printf("%lld\n", total);
    return 0;
}