All Euler problems
Project Euler

Hybrid Integers

An integer of the form p^q q^p with prime numbers p!= q is called a hybrid-integer. For example, 800 = 2^5 * 5^2 is a hybrid-integer. We define C(n) to be the number of hybrid-integers less than or...

Source sync Apr 19, 2026
Problem #0800
Level Level 10
Solved By 2,401
Languages C++, Python
Answer 1412403576
Length 314 words
number_theorysearchlinear_algebra

Problem Statement

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

An integer of the form $p^q q^p$ with prime numbers $p \neq q$ is called a hybrid-integer.

For example, $800 = 2^5 5^2$ is a hybrid-integer.

We define $C(n)$ to be the number of hybrid-integers less than or equal to $n$.

You are given $C(800) = 2$ and $C(800^{800}) = 10790$.

Find $C(800800^{800800})$.

Problem 800: Hybrid Integers

Mathematical Analysis

Key Observation: Logarithmic Transformation

A hybrid-integer has the form pqqpp^q \cdot q^p where p<qp < q are distinct primes. We need to count how many such pairs (p,q)(p, q) satisfy:

pqqp800800800800p^q \cdot q^p \leq 800800^{800800}

Taking logarithms of both sides:

qlnp+plnq800800ln800800q \ln p + p \ln q \leq 800800 \ln 800800

This transforms the problem from comparing astronomically large numbers to comparing manageable floating-point values.

Counting Strategy

For each prime pp, we find the largest prime q>pq > p such that:

qlnp+plnq800800ln800800q \ln p + p \ln q \leq 800800 \ln 800800

For a fixed pp, as qq increases, the left side grows roughly as qlnpq \ln p (since the qlnpq \ln p term dominates). So for each pp, we can use binary search among primes to find the maximum valid qq.

The number of valid primes qq for a given pp is π(qmax)π(p)\pi(q_{\max}) - \pi(p), where π\pi is the prime-counting function and qmaxq_{\max} is the largest prime satisfying the inequality.

Upper Bound on pp

When p=qp = q, the inequality becomes 2plnp800800ln8008002p \ln p \leq 800800 \ln 800800, giving approximately p800800p \leq 800800. So we only need primes up to about 800800.

Editorial

Count hybrid-integers p^q * q^p <= 800800^800800 where p, q are distinct primes. Using logarithmic transformation: qln(p) + pln(q) <= 800800*ln(800800). We generate all primes up to a sufficient bound using the Sieve of Eratosthenes. We then iterate over each prime pp (in increasing order), use binary search to find the largest prime q>pq > p with qlnp+plnqLq \ln p + p \ln q \leq L. Finally, add π(qmax)π(p)\pi(q_{\max}) - \pi(p) to the count (number of primes between p+1p+1 and qmaxq_{\max}).

Pseudocode

Generate all primes up to a sufficient bound using the Sieve of Eratosthenes
Let $L = 800800 \cdot \ln(800800)$
For each prime $p$ (in increasing order), use binary search to find the largest prime $q > p$ with $q \ln p + p \ln q \leq L$
Add $\pi(q_{\max}) - \pi(p)$ to the count (number of primes between $p+1$ and $q_{\max}$)
Stop when even $q = \text{nextprime}(p)$ violates the bound

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

  • Sieve: O(NloglogN)O(N \log \log N) where N800800N \approx 800800.
  • Main loop: For each of the N/lnN\sim N/\ln N primes pp, a binary search taking O(log(N/lnN))O(\log(N/\ln N)).
  • Total: O(NloglogN)O(N \log \log N) dominated by the sieve.

Answer

1412403576\boxed{1412403576}

Code

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

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

int main() {
    // We need to count pairs (p, q) with p < q both prime such that
    // p^q * q^p <= 800800^800800
    // Equivalently: q*ln(p) + p*ln(q) <= 800800*ln(800800)

    const int LIMIT = 800800;
    const double L = (double)LIMIT * log((double)LIMIT);

    // Sieve of Eratosthenes
    // Upper bound: q can be at most around LIMIT (when p=2, q*ln2 <= L => q ~ L/ln2 ~ 800800*ln(800800)/ln(2))
    // ln(800800) ~ 13.59, so q_max ~ 800800*13.59/0.693 ~ 15.7M
    // But we need a tighter bound. For p=2: q*ln(2) + 2*ln(q) <= L
    // q ~ L/ln(2) ~ 800800*13.59/0.693 ~ 15,700,000
    const int SIEVE_LIMIT = 16000000;

    vector<bool> is_prime(SIEVE_LIMIT + 1, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; (long long)i * i <= SIEVE_LIMIT; i++) {
        if (is_prime[i]) {
            for (int j = i * i; j <= SIEVE_LIMIT; j += i)
                is_prime[j] = false;
        }
    }

    vector<int> primes;
    primes.reserve(1100000);
    for (int i = 2; i <= SIEVE_LIMIT; i++)
        if (is_prime[i])
            primes.push_back(i);

    long long count = 0;
    int n = primes.size();

    // Two-pointer approach: for increasing p, q_max decreases
    int right = n - 1;

    for (int i = 0; i < n; i++) {
        long long p = primes[i];
        double lnp = log((double)p);

        // We need q > p, so j > i
        // q*ln(p) + p*ln(q) <= L
        // As p increases, the max valid q decreases
        if (right <= i) right = i + 1;

        // Shrink right pointer
        while (right >= 0 && right > i) {
            long long q = primes[right];
            double val = (double)q * lnp + (double)p * log((double)q);
            if (val <= L) break;
            right--;
        }

        if (right <= i) break; // no valid q for this p

        count += (long long)(right - i);
    }

    cout << count << endl;

    return 0;
}