Elliptic Curve Point Counting
For the elliptic curve E: y^2 = x^3 + x + 1 over F_p with p = 1009, find |E(F_p)|, the number of points including the point at infinity.
Problem Statement
This archive keeps the full statement, math, and original media on the page.
A Young diagram is a finite collection of (equally-sized) squares in a grid-like arrangement of rows and columns, such that
the left-most squares of all rows are aligned vertically;
the top squares of all columns are aligned horizontally;
the rows are non-increasing in size as we move top to bottom;
the columns are non-increasing in size as we move left to right.
Two examples of Young diagrams are shown below.

Two players Right and Down play a game on several Young diagrams, all disconnected from each other. Initially, a token is placed in the top-left square of each diagram. Then they take alternating turns, starting with Right. On Right's turn, Right selects a token on one diagram and moves it any number of squares to the right. On Down's turn, Down selects a token on one diagram and moves it any number of squares downwards. A player unable to make a legal move on their turn loses the game.
For $a,b,k\geq 1$ we define an -staircase to be the Young diagram where the bottom-right frontier consists of $k$ steps of vertical height $a$ and horizontal length $b$. Shown below are four examples of staircases with $(a,b,k)$ respectively $(1,1,4),$ $(5,1,1),$ $(3,3,2),$ $(2,4,3)$.

Additionally, define the weight of an $(a,b,k)$-staircase to be $a+b+k$.
Let $R(m, w)$ be the number ways of choosing $m$ staircases, each having weight not exceeding $w$, upon which Right (moving first in the game) will win the game assuming optimal play. Different orderings of the same set of staircases are to be counted separately.
For example, $R(2, 4)=7$ is illustrated below, with tokens as gray circles drawn in their initial positions.

You are also given $R(3, 9)=314104$.
Find $R(8, 64)$ giving your answer modulo $10^9+7$.
Problem 922: Elliptic Curve Point Counting
Mathematical Foundation
Theorem 1 (Point Counting Formula). Let be an elliptic curve over (with and ). Then
where is the Legendre symbol.
Proof. The point at infinity contributes 1. For each , the equation has:
- 2 solutions if is a nonzero quadratic residue (Legendre symbol ),
- 1 solution if (Legendre symbol ),
- 0 solutions if is a quadratic non-residue (Legendre symbol ).
In all cases the count is . Summing over all :
Theorem 2 (Hasse Bound). For any elliptic curve over :
Proof. (Sketch.) The Frobenius endomorphism satisfies the characteristic equation in , where is the trace of Frobenius. The eigenvalues of are complex conjugates of absolute value (by the Riemann Hypothesis for curves over finite fields, proved by Hasse for genus 1). Hence .
For : , so .
Lemma 1 (Non-singularity). The curve over is non-singular.
Proof. The discriminant is . Since and , we have .
Theorem 3 (Euler’s Criterion). For an odd prime and :
where the result is interpreted in by mapping .
Proof. Since is cyclic of order , write for a generator . Then depending on the parity of . This is exactly when is even, i.e., when is a quadratic residue.
Editorial
Count points on E: y^2 = x^3 + x + 1 over F_p, p = 1009. Key ideas:. We verify non-singularity. We then else. Finally, euler’s criterion.
Pseudocode
Verify non-singularity
else
Euler's criterion
else
Hasse bound verification
Complexity Analysis
- Time: . The loop iterates times, each iteration performing one modular exponentiation in via binary exponentiation.
- Space: auxiliary space (only running accumulators).
For , this is approximately operations — microseconds on modern hardware.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
/*
* Problem 922: Elliptic Curve Point Counting
*
* Count |E(F_p)| for E: y^2 = x^3 + x + 1, p = 1009.
*
* Formula: |E| = 1 + p + sum_{x=0}^{p-1} Legendre(f(x), p)
* where f(x) = x^3 + x + 1.
* Legendre(a, p) = a^{(p-1)/2} mod p, mapped to {-1, 0, 1}.
*
* Hasse's theorem: |p + 1 - |E|| <= 2*sqrt(p) ~ 63.6 for p=1009.
* Non-singularity: 4*1 + 27*1 = 31 != 0 mod 1009.
*
* Also implements group law for verification.
*/
long long power(long long base, long long exp, long long mod) {
long long result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = result * base % mod;
base = base * base % mod;
exp >>= 1;
}
return result;
}
int count_points(int a, int b, int p) {
int count = 1; // point at infinity
int half = (p - 1) / 2;
for (int x = 0; x < p; x++) {
long long rhs = ((long long)x * x % p * x % p + (long long)a * x % p + b) % p;
if (rhs < 0) rhs += p;
int leg;
if (rhs == 0) {
leg = 0;
} else {
leg = (int)power(rhs, half, p);
if (leg == p - 1) leg = -1;
}
count += 1 + leg;
}
return count;
}
int main() {
int p = 1009;
int answer = count_points(1, 1, p);
cout << answer << endl;
// Verify Hasse bound
int trace = p + 1 - answer;
assert(abs(trace) <= 2 * (int)sqrt((double)p) + 1);
// Verify non-singularity: 4a^3 + 27b^2 = 31 != 0 mod p
assert((4 + 27) % p != 0);
// Cross-check with brute force for p=23
int p2 = 23;
int leg_count = count_points(1, 1, p2);
int brute = 1;
for (int x = 0; x < p2; x++) {
int rhs = (x * x % p2 * x % p2 + x + 1) % p2;
if (rhs < 0) rhs += p2;
for (int y = 0; y < p2; y++)
if (y * y % p2 == rhs) brute++;
}
assert(leg_count == brute);
return 0;
}
"""
Problem 922: Elliptic Curve Point Counting
Count points on E: y^2 = x^3 + x + 1 over F_p, p = 1009.
Key ideas:
- |E(F_p)| = 1 + p + sum of Legendre symbols (f(x)/p).
- Legendre symbol via Euler's criterion: a^{(p-1)/2} mod p.
- Hasse bound: |p+1 - |E|| <= 2*sqrt(p) ~ 63.6.
- Non-singularity: 4a^3 + 27b^2 = 31 != 0 mod 1009.
Methods:
1. Legendre symbol summation (O(p log p))
2. Brute-force (x,y) enumeration (O(p^2))
3. Group law verification
"""
from math import isqrt
def count_points_legendre(a: int, b: int, p: int) -> int:
"""Count |E(F_p)| for y^2 = x^3 + ax + b via Legendre symbols."""
count = 1 # point at infinity
half = (p - 1) // 2
for x in range(p):
rhs = (pow(x, 3, p) + a * x + b) % p
if rhs == 0:
leg = 0
else:
leg = pow(rhs, half, p)
if leg == p - 1:
leg = -1
count += 1 + leg
return count
def count_points_brute(a: int, b: int, p: int) -> int:
"""Count by checking all (x,y) pairs."""
count = 1 # point at infinity
for x in range(p):
rhs = (pow(x, 3, p) + a * x + b) % p
for y in range(p):
if (y * y) % p == rhs:
count += 1
return count
# Elliptic curve group operations
def ec_add(P, Q, a, p):
"""Add two points on y^2 = x^3 + ax + b over F_p."""
if P is None: return Q
if Q is None: return P
x1, y1 = P
x2, y2 = Q
if x1 == x2 and (y1 + y2) % p == 0:
return None # P + (-P) = O
if x1 == x2:
lam = (3 * x1 * x1 + a) * pow(2 * y1, p - 2, p) % p
else:
lam = (y2 - y1) * pow(x2 - x1, p - 2, p) % p
x3 = (lam * lam - x1 - x2) % p
y3 = (lam * (x1 - x3) - y1) % p
return (x3, y3)
# Solve
p = 1009
answer = count_points_legendre(1, 1, p)
# Verify non-singularity
assert (4 * 1 + 27 * 1) % p != 0
# Verify Hasse bound
trace = p + 1 - answer
assert abs(trace) <= 2 * isqrt(p) + 1
# Verify against brute force for small prime
p_small = 23
assert count_points_legendre(1, 1, p_small) == count_points_brute(1, 1, p_small)
print(answer)