Open Source · 7 Languages · 900+ Problems

Project Euler Solutions

Complete solutions in C++, Python & Java — with step-by-step mathematical explanations

All Problems

Problem 148: Exploring Pascal's Triangle

View on Project Euler

Project Euler Problem 148 Solution

EulerSolve provides an optimized solution for Project Euler Problem 148, Exploring Pascal's Triangle, with C++, Python, Java, and a step-by-step mathematical explanation.

Problem Summary For the first \(10^9\) rows of Pascal's triangle, count how many binomial coefficients are not divisible by 7. If row \(n\) is written as \(\binom{n}{0},\binom{n}{1},\dots,\binom{n}{n}\), then a brute-force approach would have to inspect an enormous number of entries, so the only viable route is to exploit the arithmetic structure of binomial coefficients modulo 7. Let \(r(n)\) denote the number of entries in row \(n\) that are not divisible by 7, and let \(F(N)=\sum_{n=0}^{N-1} r(n)\). The required answer is \(F(10^9)\). Mathematical Approach Lucas' theorem turns one row into a digit product Write \(n\) and \(k\) in base 7 as $n=\sum_i d_i 7^i,\qquad k=\sum_i e_i 7^i.$ Lucas' theorem states that for a prime \(p\), $\binom{n}{k}\equiv \prod_i \binom{d_i}{e_i}\pmod p.$ With \(p=7\), the product is nonzero modulo 7 exactly when every digit satisfies \(e_i\le d_i\). For one fixed digit \(d_i\), there are \(d_i+1\) allowed choices for \(e_i\). Therefore the number of entries in row \(n\) that survive modulo 7 is $r(n)=\prod_i (d_i+1).$ This is the central object of the problem: each row is reduced to a simple product of its base-7 digits plus one. Why complete blocks of \(7^m\) rows collapse to \(28^m\) Consider all rows with \(0\le n<7^m\)....

Detailed mathematical approach

Problem Summary

For the first \(10^9\) rows of Pascal's triangle, count how many binomial coefficients are not divisible by 7. If row \(n\) is written as \(\binom{n}{0},\binom{n}{1},\dots,\binom{n}{n}\), then a brute-force approach would have to inspect an enormous number of entries, so the only viable route is to exploit the arithmetic structure of binomial coefficients modulo 7.

Let \(r(n)\) denote the number of entries in row \(n\) that are not divisible by 7, and let \(F(N)=\sum_{n=0}^{N-1} r(n)\). The required answer is \(F(10^9)\).

Mathematical Approach

Lucas' theorem turns one row into a digit product

Write \(n\) and \(k\) in base 7 as

$n=\sum_i d_i 7^i,\qquad k=\sum_i e_i 7^i.$

Lucas' theorem states that for a prime \(p\),

$\binom{n}{k}\equiv \prod_i \binom{d_i}{e_i}\pmod p.$

With \(p=7\), the product is nonzero modulo 7 exactly when every digit satisfies \(e_i\le d_i\). For one fixed digit \(d_i\), there are \(d_i+1\) allowed choices for \(e_i\). Therefore the number of entries in row \(n\) that survive modulo 7 is

$r(n)=\prod_i (d_i+1).$

This is the central object of the problem: each row is reduced to a simple product of its base-7 digits plus one.

Why complete blocks of \(7^m\) rows collapse to \(28^m\)

Consider all rows with \(0\le n<7^m\). Their base-7 representations use exactly \(m\) digits after padding with leading zeros, and each digit can be chosen independently from \(0\) through \(6\). Summing the row formula over the entire block factorizes:

$F(7^m)=\sum_{d_{m-1}=0}^{6}\cdots\sum_{d_0=0}^{6}\prod_{i=0}^{m-1}(d_i+1)=\prod_{i=0}^{m-1}\sum_{d=0}^{6}(d+1)=28^m.$

The number \(28\) is just \(1+2+\cdots+7\). That is why every unrestricted base-7 suffix of length \(m\) contributes a factor of \(28^m\).

A recurrence for an arbitrary upper bound

Now write

$N=a\cdot 7^m+b,\qquad 0\le a\le 6,\qquad 0\le b<7^m.$

Rows whose leading base-7 digit is \(x<a\) form a complete block of size \(7^m\). Their leading digit contributes a factor of \(x+1\), and the remaining \(m\) digits contribute \(28^m\). The unfinished part keeps the leading digit \(a\), so every row there gets an additional factor of \(a+1\). Hence

$F(N)=\sum_{x=0}^{a-1}(x+1)28^m+(a+1)F(b).$

Using \(\sum_{x=0}^{a-1}(x+1)=a(a+1)/2\), this becomes

$F(N)=\frac{a(a+1)}{2}\,28^m+(a+1)F(b).$

This recurrence is the mathematical reason the problem can be solved digit by digit from the most significant base-7 digit to the least significant one.

Worked example: the first 100 rows

The standard checkpoint value is the first 100 rows. Since \(100=202_7\), we split the interval into complete and partial leading-digit blocks:

$F(202_7)=(1+2)\cdot 28^2+3\cdot F(2_7).$

The first term counts all rows below \(200_7\): leading digit \(0\) contributes \(1\cdot 28^2\), and leading digit \(1\) contributes \(2\cdot 28^2\). For the remaining rows \(200_7\) and \(201_7\), the fixed leading digit \(2\) contributes a factor of \(3\), and the suffix count is

$F(2_7)=1+2=3.$

Therefore

$F(100)=3\cdot 784+3\cdot 3=2361.$

This is exactly the published sample total. It also clarifies the indexing: \(F(100)\) counts rows \(0\) through \(99\), because \(100\) is the upper bound, not an included row number.

The closed digit formula evaluated by the implementation

If

$N=(a_0a_1\cdots a_{L-1})_7$

is written from most significant to least significant digit, then repeatedly applying the recurrence gives

$F(N)=\sum_{i=0}^{L-1}\left(\prod_{j=0}^{i-1}(a_j+1)\right)\left(\sum_{x=0}^{a_i-1}(x+1)\right)28^{L-1-i}.$

The empty product is 1. The prefix product records the contribution of the digits already fixed, while the power of 28 records the total contribution of the free suffix. This formula is exactly what the implementations accumulate.

How the Code Works

The C++, Python, and Java implementations first convert \(10^9\) to base 7. In this problem, \(10^9=33531600616_7\), so the entire computation touches only 11 digits. They also precompute the powers \(28^t\), because a suffix of \(t\) unrestricted base-7 digits always contributes \(28^t\).

The main loop scans the base-7 digits from left to right. At a digit \(d\), the implementation adds the contribution of every smaller digit \(0,1,\dots,d-1\) placed at that position, multiplies each contribution by the prefix product from the already fixed higher digits, and multiplies again by the appropriate power of 28 for the remaining free suffix.

After those smaller-digit branches are counted, the actual digit \(d\) is folded into the prefix product by multiplying by \(d+1\). The inner loop is tiny because a base-7 digit has at most seven possible values, so the direct summation is still constant time. The three languages differ only in numeric representation: Python uses arbitrary-precision integers, Java uses big integers, and C++ uses a 128-bit integer so the final count is handled safely. One implementation also keeps the checkpoint values for the first 7 rows and the first 100 rows.

Complexity Analysis

If \(L=\lfloor\log_7 N\rfloor+1\), the algorithm performs \(L\) digit steps, and each step checks at most 7 smaller digits. The running time is therefore \(O(L)=O(\log_7 N)\). For \(N=10^9\), this means only 11 iterations of the outer loop.

The memory usage is also \(O(L)\): one list of digits, one list of powers of 28, and a few integer accumulators. Compared with a naive sweep through every entry of every row, this is a complete collapse in problem size.

Footnotes and References

  1. Problem page: https://projecteuler.net/problem=148
  2. Lucas' theorem: Wikipedia - Lucas's theorem
  3. Pascal's triangle: Wikipedia - Pascal's triangle
  4. Binomial coefficient: Wikipedia - Binomial coefficient
  5. Positional notation: Wikipedia - Positional notation

Mathematical approach · C++ solution · Python solution · Java solution

Previous: Problem 147 · All Project Euler solutions · Next: Problem 149

Need help with a problem? Ask me! 💡
e
✦ Euler GLM 5.2
Hi! I'm Euler. Ask me anything about Project Euler problems, math concepts, or solution approaches! 🧮