📜  优化的Euler Totient函数进行多次评估

📅  最后修改于: 2021-05-06 17:40:13             🧑  作者: Mango

ÈulerŤotient˚F结(ETF)Φ(N),用于将输入n是数字的计数在{1,2,3,…,N}互质到n,即,其GCD的数字(最大公约数),其中n为1。
例子:

Φ(5) = 4
gcd(1, 5) is 1, gcd(2, 5) is 1, 
gcd(3, 5) is 1 and gcd(4, 5) is 1

Φ(6) = 2
gcd(1, 6) is 1 and gcd(5, 6) is 1,

我们已经讨论了不同的计算Euler Totient函数的方法,这些方法适用于单个输入。在必须多次调用欧拉Totient函数(例如10 ^ 5次)的问题中,简单的解决方案将导致TLE(超过时间限制)。这个想法是使用Eratosthenes筛。

使用Eratosthenes筛子找出所有最大数达到最大限制(例如10 ^ 5)的质数。
为了计算Φ(n),我们执行以下操作。

  1. 将结果初始化为n。
  2. 遍历所有小于或等于n的平方根的素数(这与简单方法不同。这不是遍历所有小于或等于平方根的数,而是仅遍历素数)。令当前素数为p。我们检查p是否除以n,如果是,则通过重复将其除以n来从n中删除所有出现的p。我们还将结果减少n / p(许多数字的GCD不会与n一起为1)。
  3. 最后我们返回结果。
C++
// C++ program to efficiently compute values
// of euler totient function for multiple inputs.
#include 
using namespace std;
  
#define ll long long
const int MAX = 100001;
  
// Stores prime numbers upto MAX - 1 values
vector p;
  
// Finds prime numbers upto MAX-1 and
// stores them in vector p
void sieve()
{
    ll isPrime[MAX+1];
  
    for (ll i = 2; i<= MAX; i++)
    {
        // if prime[i] is not marked before
        if (isPrime[i] == 0)
        {
            // fill vector for every newly
            // encountered prime
            p.push_back(i);
  
            // run this loop till square root of MAX,
            // mark the index i * j as not prime
            for (ll j = 2; i * j<= MAX; j++)
                isPrime[i * j]= 1;
        }
    }
}
  
// function to find totient of n
ll phi(ll n)
{
    ll res = n;
  
    // this loop runs sqrt(n / ln(n)) times
    for (ll i=0; p[i]*p[i] <= n; i++)
    {
        if (n % p[i]== 0)
        {
            // subtract multiples of p[i] from r
            res -= (res / p[i]);
  
            // Remove all occurrences of p[i] in n
            while (n % p[i]== 0)
               n /= p[i];
        }
    }
  
    // when n has prime factor greater
    // than sqrt(n)
    if (n > 1)
       res -= (res / n);
  
    return res;
}
  
// Driver code
int main()
{
    // preprocess all prime numbers upto 10 ^ 5
    sieve();
    cout << phi(11) << "\n";
    cout << phi(21) << "\n";
    cout << phi(31) << "\n";
    cout << phi(41) << "\n";
    cout << phi(51) << "\n";
    cout << phi(61) << "\n";
    cout << phi(91) << "\n";
    cout << phi(101) << "\n";
    return 0;
}


Java
// Java program to efficiently compute values 
// of euler totient function for multiple inputs. 
import java.util.*; 
  
class GFG{ 
static int MAX = 100001; 
  
// Stores prime numbers upto MAX - 1 values 
static ArrayList p = new ArrayList();
  
// Finds prime numbers upto MAX-1 and 
// stores them in vector p 
static void sieve() 
{ 
    int[] isPrime=new int[MAX+1]; 
  
    for (int i = 2; i<= MAX; i++) 
    { 
        // if prime[i] is not marked before 
        if (isPrime[i] == 0) 
        { 
            // fill vector for every newly 
            // encountered prime 
            p.add(i); 
  
            // run this loop till square root of MAX, 
            // mark the index i * j as not prime 
            for (int j = 2; i * j<= MAX; j++) 
                isPrime[i * j]= 1; 
        } 
    } 
} 
  
// function to find totient of n 
static int phi(int n) 
{ 
    int res = n; 
  
    // this loop runs sqrt(n / ln(n)) times 
    for (int i=0; p.get(i)*p.get(i) <= n; i++) 
    { 
        if (n % p.get(i)== 0) 
        { 
            // subtract multiples of p[i] from r 
            res -= (res / p.get(i)); 
  
            // Remove all occurrences of p[i] in n 
            while (n % p.get(i)== 0) 
            n /= p.get(i); 
        } 
    } 
  
    // when n has prime factor greater 
    // than sqrt(n) 
    if (n > 1) 
    res -= (res / n); 
  
    return res; 
} 
  
// Driver code 
public static void main(String[] args) 
{ 
    // preprocess all prime numbers upto 10 ^ 5 
    sieve(); 
    System.out.println(phi(11)); 
    System.out.println(phi(21)); 
    System.out.println(phi(31)); 
    System.out.println(phi(41)); 
    System.out.println(phi(51)); 
    System.out.println(phi(61)); 
    System.out.println(phi(91)); 
    System.out.println(phi(101)); 
   
} 
}
// this code is contributed by mits


Python3
# Python3 program to efficiently compute values 
# of euler totient function for multiple inputs. 
  
MAX = 100001; 
  
# Stores prime numbers upto MAX - 1 values 
p = [];
  
# Finds prime numbers upto MAX-1 and 
# stores them in vector p 
def sieve(): 
  
    isPrime = [0] * (MAX + 1); 
  
    for i in range(2, MAX + 1): 
          
        # if prime[i] is not marked before 
        if (isPrime[i] == 0): 
              
            # fill vector for every newly 
            # encountered prime 
            p.append(i); 
  
            # run this loop till square root of MAX, 
            # mark the index i * j as not prime
            j = 2;
            while (i * j <= MAX): 
                isPrime[i * j]= 1;
                j += 1;
  
# function to find totient of n 
def phi(n):
  
    res = n; 
  
    # this loop runs sqrt(n / ln(n)) times
    i = 0;
    while (p[i] * p[i] <= n): 
        if (n % p[i]== 0): 
              
            # subtract multiples of p[i] from r 
            res -= int(res / p[i]); 
  
            # Remove all occurrences of p[i] in n 
            while (n % p[i]== 0):
                n = int(n / p[i]); 
        i += 1;
  
    # when n has prime factor greater 
    # than sqrt(n) 
    if (n > 1):
        res -= int(res / n); 
  
    return res; 
  
# Driver code 
  
# preprocess all prime numbers upto 10 ^ 5 
sieve(); 
print(phi(11)); 
print(phi(21)); 
print(phi(31)); 
print(phi(41)); 
print(phi(51)); 
print(phi(61)); 
print(phi(91)); 
print(phi(101)); 
  
# This code is contributed by mits


C#
// C# program to efficiently compute values 
// of euler totient function for multiple inputs. 
using System;
using System.Collections;
class GFG{ 
static int MAX = 100001; 
  
// Stores prime numbers upto MAX - 1 values 
static ArrayList p = new ArrayList();
  
// Finds prime numbers upto MAX-1 and 
// stores them in vector p 
static void sieve() 
{ 
    int[] isPrime=new int[MAX+1]; 
  
    for (int i = 2; i<= MAX; i++) 
    { 
        // if prime[i] is not marked before 
        if (isPrime[i] == 0) 
        { 
            // fill vector for every newly 
            // encountered prime 
            p.Add(i); 
  
            // run this loop till square root of MAX, 
            // mark the index i * j as not prime 
            for (int j = 2; i * j<= MAX; j++) 
                isPrime[i * j]= 1; 
        } 
    } 
} 
  
// function to find totient of n 
static int phi(int n) 
{ 
    int res = n; 
  
    // this loop runs sqrt(n / ln(n)) times 
    for (int i=0; (int)p[i]*(int)p[i] <= n; i++) 
    { 
        if (n % (int)p[i]== 0) 
        { 
            // subtract multiples of p[i] from r 
            res -= (res / (int)p[i]); 
  
            // Remove all occurrences of p[i] in n 
            while (n % (int)p[i]== 0) 
            n /= (int)p[i]; 
        } 
    } 
  
    // when n has prime factor greater 
    // than sqrt(n) 
    if (n > 1) 
    res -= (res / n); 
  
    return res; 
} 
  
// Driver code 
static void Main() 
{ 
    // preprocess all prime numbers upto 10 ^ 5 
    sieve(); 
    Console.WriteLine(phi(11)); 
    Console.WriteLine(phi(21)); 
    Console.WriteLine(phi(31)); 
    Console.WriteLine(phi(41)); 
    Console.WriteLine(phi(51)); 
    Console.WriteLine(phi(61)); 
    Console.WriteLine(phi(91)); 
    Console.WriteLine(phi(101)); 
  
} 
}
// this code is contributed by mits


PHP
 1) 
    $res -= (int)($res / $n); 
  
    return $res; 
} 
  
// Driver code 
   
    // preprocess all prime numbers upto 10 ^ 5 
    sieve(); 
    print(phi(11)."\n"); 
    print(phi(21)."\n"); 
    print(phi(31)."\n"); 
    print(phi(41)."\n"); 
    print(phi(51)."\n"); 
    print(phi(61)."\n"); 
    print(phi(91)."\n"); 
    print(phi(101)."\n"); 
  
// this code is contributed by mits
?>


输出:

10
12
30
40
32
60
72
100