Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion src/algebra/phi-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ void phi_1_to_n(int n) {
}
```


## Divisor sum property { #divsum}

This interesting property was established by Gauss:
Expand Down Expand Up @@ -125,6 +124,53 @@ void phi_1_to_n(int n) {
}
```


#### Finding the totient from $L$ to $R$ using the [segmented sieve](sieve-of-eratosthenes.md#segmented-sieve) { data-toc-label="Finding the totient from L to R using the segmented sieve" }
If we need the totient of all numbers between $L$ and $R$, we can use the [segmented sieve](sieve-of-eratosthenes.md#segmented-sieve) approach.

The algorithm first precomputes all primes up to $\sqrt{R}$ using a [linear sieve](prime-sieve-linear.md) in $O(\sqrt{R})$ time and space; then for each number in the range $[L, R]$, it applies the standard φ formula $\phi(n) = n \cdot \prod_{p | n} \left(1 - \frac{1}{p}\right)$ by iterating over these primes while maintaining a `rem` array for the unfactored part—if `rem[i] > 1` after processing all small primes, it indicates a large prime factor greater than $\sqrt{R}$ handled in a final pass—so the range computation runs in $O((R - L + 1) \log \log R)$. To use this, call `primes = linear_sieve(sqrt(MAX_R) + 1)` once at startup; then `phi[i - L]` gives $\phi(i)$ for each $i \in [L, R]$.


```cpp
const long long MAX_RANGE = 1e6 + 6, MAX_R = 1e14;
vector<long long> primes;
long long phi[MAX_RANGE], rem[MAX_RANGE];

vector<int> linear_sieve(int n) {
vector<bool> composite(n + 1, 0);
vector<int> prime;

composite[0] = composite[1] = 1;

for(int i = 2; i <= n; i++) {
if(!composite[i]) prime.push_back(i);
for(int j = 0; j < prime.size() && i * prime[j] <= n; j++) {
composite[i * prime[j]] = true;
if(i % prime[j] == 0) break;
}
}
return prime;
}

void segmented_phi(long long L, long long R) {
for(long long i = L; i <= R; i++) {
rem[i - L] = i;
phi[i - L] = i;
}

for(long long &i : primes) {
for(long long j = max(i * i, (L + i - 1) / i * i); j <= R; j += i) {
phi[j - L] -= phi[j - L] / i;
while(rem[j - L] % i == 0) rem[j - L] /= i;
}
}

for(long long i = 0; i < R - L + 1; i++) {
if(rem[i] > 1) phi[i] -= phi[i] / rem[i];
}
}
```

## Application in Euler's theorem { #application }

The most famous and important property of Euler's totient function is expressed in **Euler's theorem**:
Expand Down