Project Euler Problem 875

For a positive integer n we define q(n) to be the number of solutions to: where 0 leq ai, bi lt n.

Project Euler Problem 875

Solution

Answer: 79645946

Let

$$R_n(t)=#{(x_1,x_2,x_3,x_4)\in (\mathbb Z/n\mathbb Z)^4: x_1^2+x_2^2+x_3^2+x_4^2\equiv t\pmod n}.$$

Then

$$q(n)=\sum_{t \bmod n} R_n(t)^2,$$

because choosing two 4-tuples with the same quadratic sum is exactly the condition in the problem.

We must compute

$$Q(N)=\sum_{n\le N} q(n), \qquad N=12345678,$$

modulo $1001961001$.


1. Mathematical analysis

Step 1: Fourier expansion

Using additive characters,

$$R_n(t)=\frac1n\sum_{h\bmod n} \left(\sum_{x\bmod n} e^{2\pi i h x^2/n}\right)^4 e^{-2\pi i ht/n}.$$

Define the quadratic Gauss sum

$$G_n(h)=\sum_{x\bmod n} e^{2\pi i h x^2/n}.$$

Then

$$R_n(t)=\frac1n\sum_{h\bmod n} G_n(h)^4 e^{-2\pi i ht/n}.$$

Therefore

$$q(n) =\sum_t R_n(t)^2 =\frac1n\sum_{h\bmod n}|G_n(h)|^8.$$

So the problem reduces entirely to evaluating quadratic Gauss sums.


Step 2: Odd prime powers

For odd $n$, the classical Gauss sum identity gives

$$|G_n(h)|^2=n\gcd(h,n).$$

Hence

$$|G_n(h)|^8=n^4\gcd(h,n)^4,$$

and therefore

$$q(n)=n^3\sum_{h\bmod n}\gcd(h,n)^4.$$

Now group terms by $d=\gcd(h,n)$.

The number of $h$ with $\gcd(h,n)=d$ is $\varphi(n/d)$. Thus

$$q(n)=n^3\sum_{d\mid n} d^4\varphi(n/d).$$

This is multiplicative.

For an odd prime power $p^k$,

$$q(p^k) =p^{3k}\sum_{i=0}^k p^{4i}\varphi(p^{k-i}).$$

Since

$$\varphi(p^m)= \begin{cases} p^m-p^{m-1}, & m\ge1,\ 1,&m=0, \end{cases}$$

we obtain

$$q(p^k) = p^{7k} +(p-1)\sum_{i=0}^{k-1} p^{4k-1+3i}.$$

Equivalently, the recurrence

$$q(p^k)=p^7 q(p^{k-1})+(p-1)p^{4k-1}.$$

For $k=1$,

$$q(p)=p^7+(p-1)p^3.$$

Example:

$$q(3)=3^7+2\cdot 3^3=2187+54=2241.$$

Correct.


Step 3: Powers of 2

The 2-adic Gauss sums behave differently.

A direct evaluation gives

$$q(2^k)=\frac{2^{7k+3}-2^{4k}}7.$$

Equivalently,

$$q(2^k)=128,q(2^{k-1})+2^{4k+3}.$$

Check:

$$q(4)=\frac{2^{17}-2^8}{7} =\frac{131072-256}{7} =18432,$$

matching the statement.


Step 4: Multiplicativity

Since the formula comes from Gauss sums and CRT factorisation,

$$q(ab)=q(a)q(b)\qquad (\gcd(a,b)=1).$$

Thus $q$ is multiplicative.

So we can compute all values up to $N$ using a linear sieve.


2. Python implementation

from array import array

MOD = 1001961001
N = 12345678

# q[n]      = q(n) mod MOD
# pp[n]     = highest prime power dividing n
# g[n]      = q(pp[n]) mod MOD

q = array('I', [0]) * (N + 1)
pp = array('I', [0]) * (N + 1)
g = array('I', [0]) * (N + 1)

primes = array('I')

q[1] = 1
g[1] = 1

answer = 1

for n in range(2, N + 1):

    # n is prime
    if pp[n] == 0:
        primes.append(n)
        pp[n] = n

        if n == 2:
            gn = 128
        else:
            gn = (pow(n, 7, MOD) + (n - 1) * pow(n, 3, MOD)) % MOD

        g[n] = gn
        q[n] = gn

    qn = q[n]

    # Euler linear sieve transitions
    for p in primes:
        m = n * p
        if m > N:
            break

        if n % p != 0:
            # new prime factor
            pp[m] = p

            if p == 2:
                gp = 128
            else:
                gp = (pow(p, 7, MOD) +
                      (p - 1) * pow(p, 3, MOD)) % MOD

            g[m] = gp
            q[m] = (qn * gp) % MOD

        else:
            # extending prime power
            pp_new = pp[n] * p
            pp[m] = pp_new

            old_g = g[n]

            if p == 2:
                # q(2^k)=128*q(2^(k-1))+2^(4k+3)
                new_g = (
                    128 * old_g
                    + 8 * pow(pp_new, 4, MOD)
                ) % MOD

            else:
                # q(p^k)=p^7*q(p^(k-1))+(p-1)p^(4k-1)
                term = (
                    (p - 1)
                    * (pow(pp_new, 4, MOD) * pow(p, -1, MOD) % MOD)
                ) % MOD

                new_g = (
                    pow(p, 7, MOD) * old_g + term
                ) % MOD

            g[m] = new_g

            # multiplicativity:
            # n = (n // pp[n]) * pp[n]
            q[m] = (q[n // pp[n]] * new_g) % MOD

            break

    answer += q[n]
    answer %= MOD

print(answer)

3. Code walkthrough

Arrays

  • q[n] stores $q(n)\pmod{M}$.
  • pp[n] stores the highest power of the smallest repeated prime.
  • g[n] stores the prime-power contribution $q(p^k)$.

This is the standard structure for a multiplicative-function linear sieve.


Prime case

For an odd prime $p$,

$$q(p)=p^7+(p-1)p^3.$$

For $p=2$,

$$q(2)=128.$$

These initialise the sieve.


Coprime extension

If $p\nmid n$, then by multiplicativity,

$$q(np)=q(n)q(p).$$


Prime-power extension

If $p\mid n$, then we extend $p^k\to p^{k+1}$.

For odd $p$,

$$q(p^k)=p^7q(p^{k-1})+(p-1)p^{4k-1}.$$

For $p=2$,

$$q(2^k)=128q(2^{k-1})+2^{4k+3}.$$


Verification on the sample

Running the program for $N=10$ gives

$$Q(10)=18573381,$$

exactly matching the problem statement.


4. Final verification

The computation:

  • uses exact multiplicative formulas,
  • matches all tested small values,
  • reproduces the given check value $Q(10)$,
  • runs in linear time up to $12{,}345{,}678$.

The resulting value modulo $1001961001$ is:

Answer: 79645946