MHB How to Efficiently Compute Euler's Totient Function for Large Ranges?

  • Thread starter Thread starter Saitama
  • Start date Start date
  • Tags Tags
    Euler Function
AI Thread Summary
The discussion centers around solving the SPOJ problem ETFS, which requires calculating the Euler's totient function, phi(n), for a range of integers from a to b. The challenge arises from the constraints, where a and b can be as large as 10^14, making a naive O(√n) approach impractical due to time limits. The provided code attempts to optimize the calculation by leveraging properties of the totient function, specifically using relationships for even and odd integers to reduce the number of calculations needed.However, users point out that even with these optimizations, the solution still experiences time limit exceeded (TLE) errors. Suggestions include using more advanced factorization algorithms, such as Pollard's Rho, which can factor numbers more efficiently than trial division. Additionally, employing a sieve or dynamic programming approach is recommended to handle the range of consecutive integers effectively. The discussion highlights the need for efficient algorithms in number theory problems, particularly when dealing with large input sizes.
Saitama
Messages
4,244
Reaction score
93
Following is the problem I am trying to solve: SPOJ.com - Problem ETFS

In number theory, the totient phi(n) of a positive integer n is defined to be the number of positive integers less than or equal to n that are coprime to n.

Input

The lonely line in input contains two integers a, b.

Output

Print phi(n) for n from a to b (inclusive).

Example

Input:
1 5

Output:
1
1
2
2
4

Constraints

0 < a < b < 10^14
b - a < 10^5

Here is my code:

Code:
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

typedef long long ll;

ll solve(ll n)
{
	ll i, ans=n;
	for(i=2; i*i<=n; ++i)
	{
		if(n%i==0)
			ans-=ans/i;
		while(n%i==0)
			n/=i;
	}
	if(n>1)
		ans-=ans/n;
	return ans;
}

int main() {
	ll T, n, a, b, i;
	scanf("%lld %lld", &a, &b);
	vector<ll> x(b-a+1, -1);
	for(n=a; n<=b; ++n)
	{
		if(x[n-a]==-1)
		{
			x[n-a]=solve(n);
			if(2*n<=b)
			{
				if(n%2) x[2*n-a]=x[n-a];
				else x[2*n-a]=2*x[n-a];
			}
			for(i=n*4; i<=b; i*=2)
			{
				x[i-a]=2*x[i/2-a];
			}
		}
	}
	for(i=0; i<b-a+1; ++i)
		printf("%lld\n", x[i]);
	return 0;
}

Some explanation of what I am trying to do.

The naive approach i.e finding $\phi (n)$ of every number in the given range using the $O(\sqrt{n})$ won't work. So whenever I have found $\phi(n)$, I use the following relation: $\phi(2n)=2\phi(n)$ if $n$ is even and $\phi(2n)=\phi(n)$ is $n$ is odd. With this, I don't have to run the solve() function ($O(\sqrt{n}$) for every integer in the range but even with this optimisation, I get TLE. :(

Please help. Thanks!
 
Technology news on Phys.org
Hi Pranav,

Perhaps we can use that
\begin{cases}\phi(p)&=p-1\\\phi(p^n)&=(p-1)p^{n-1}\\\phi(a\cdot p^n)&=\phi(a)\cdot\phi(p^n) &\text{ if }p\nmid a\end{cases}
Then we might apply a sieve or dynamic programming.
 
Hint: trial division is not the only factorization algorithm that exists. There are many more advanced algorithms, some of which are easy to implement and will pretty much instantly factor your input integers up to 10^14. For instance, Pollard's Rho is pretty simple to implement, and in practice runs in worst case $O(\sqrt[4]{n})$.

Then you can use I Like Serena's suggestions to take advantage of the fact that you have to factor a range of consecutive integers, etc...
 
Dear Peeps I have posted a few questions about programing on this sectio of the PF forum. I want to ask you veterans how you folks learn program in assembly and about computer architecture for the x86 family. In addition to finish learning C, I am also reading the book From bits to Gates to C and Beyond. In the book, it uses the mini LC3 assembly language. I also have books on assembly programming and computer architecture. The few famous ones i have are Computer Organization and...
I have a quick questions. I am going through a book on C programming on my own. Afterwards, I plan to go through something call data structures and algorithms on my own also in C. I also need to learn C++, Matlab and for personal interest Haskell. For the two topic of data structures and algorithms, I understand there are standard ones across all programming languages. After learning it through C, what would be the biggest issue when trying to implement the same data...
Back
Top