Project Euler Problem 800
An integer of the form p^q q^p with prime numbers p neq q is called a hybrid-integer.
Solution
Answer: 1412403576
Let
$$H(p,q)=p^q q^p$$
with distinct primes $p\neq q$. We must count the number of unordered prime pairs $(p,q)$ such that
$$p^q q^p \le 800800^{800800}.$$
Define
$$L = \log\left(800800^{800800}\right)=800800\log(800800).$$
Taking logarithms transforms the inequality into
$$q\log p + p\log q \le L.$$
So the problem becomes:
Count prime pairs $p<q$ satisfying
$$q\log p + p\log q \le L.$$
1. Mathematical analysis
Step 1 — Rewrite using logarithms
Because logarithm is strictly increasing,
$$p^q q^p \le N \iff q\log p + p\log q \le \log N.$$
For the target value,
$$N = 800800^{800800},$$
so
$$L = 800800\log(800800).$$
Step 2 — Monotonicity
For fixed $p$, define
$$f_p(q)=q\log p + p\log q.$$
For $q>1$,
$$f_p'(q)=\log p + \frac{p}{q}>0,$$
so $f_p(q)$ is strictly increasing in $q$.
Therefore, for each prime $p$, there is a largest prime $q$ satisfying the inequality. This allows a two-pointer approach.
Step 3 — Prime bound
The largest possible $q$ occurs when $p=2$:
$$q\log 2 + 2\log q \le L.$$
Hence approximately
$$q \lesssim \frac{L}{\log 2}.$$
Numerically this is about $1.57\times 10^7$, which is entirely feasible for a sieve of Eratosthenes.
Step 4 — Two-pointer counting
Let the primes be
$$p_0<p_1<\cdots<p_{m-1}.$$
We maintain a pointer $j$ starting at the largest prime index.
For each $i$:
- decrease $j$ while
$$p_j\log p_i + p_i\log p_j > L,$$
- then every prime between indices $i+1$ and $j$ works.
Add
$$j-i$$
to the count.
Because $j$ only moves downward, the algorithm is linear after sieving.
2. Python implementation
from math import log, isqrt
def hybrid_count(base, exponent):
# L = log(base^exponent)
L = exponent * log(base)
# Maximum possible q occurs roughly when p = 2
limit = int(L / log(2)) + 10
# Sieve of Eratosthenes
sieve = bytearray(b'\x01') * (limit + 1)
sieve[0:2] = b'\x00\x00'
for p in range(2, isqrt(limit) + 1):
if sieve[p]:
start = p * p
sieve[start:limit + 1:p] = (
b'\x00' * (((limit - start) // p) + 1)
)
primes = [i for i, v in enumerate(sieve) if v]
logs = [log(p) for p in primes]
# Two-pointer counting
total = 0
j = len(primes) - 1
for i, p in enumerate(primes):
while j > i and primes[j] * logs[i] + p * logs[j] > L:
j -= 1
if j <= i:
break
total += (j - i)
return total
# Checks from the problem statement
print(hybrid_count(800, 1)) # C(800)
print(hybrid_count(800, 800)) # C(800^800)
# Final answer
print(hybrid_count(800800, 800800))
3. Code walkthrough
Computing $L$
L = exponent * log(base)
Since
$$\log(base^{exponent}) = exponent \log(base),$$
this avoids huge integers entirely.
Generating primes
We sieve all primes up to approximately
$$\frac{L}{\log 2}.$$
This safely includes every possible candidate for $q$.
Two-pointer section
while j > i and primes[j] * logs[i] + p * logs[j] > L:
j -= 1
This shrinks the upper bound until the inequality holds.
Then all primes from index $i+1$ through $j$ are valid.
4. Verification
The program reproduces the given examples:
$$C(800)=2$$
and
$$C(800^{800})=10790.$$
So the method is consistent with the problem statement.
Running the same algorithm for
$$800800^{800800}$$
gives:
$$1412403576.$$
Answer: 1412403576