Finished 69 (nice), wasn't too hard but my solution is pretty slow for some reason (19 s)

This commit is contained in:
2021-11-14 21:24:24 +01:00
parent d06da3219a
commit ec1fae253d

101
projecteuler/069/main.cpp Normal file
View File

@@ -0,0 +1,101 @@
/* Totient maximum
Euler's Totient function, φ(n) [sometimes called the phi function], is used to determine the number of numbers less than n which are relatively prime to n. For example, as 1, 2, 4, 5, 7, and 8, are all less than nine and relatively prime to nine, φ(9)=6.
It can be seen that n=6 produces a maximum n/φ(n) for n ≤ 10.
Find the value of n ≤ 1,000,000 for which n/φ(n) is a maximum.
*/
#include <bits/stdc++.h>
using namespace std;
const int MAX = 1000000;
vector<int> sieve(int n){
vector<bool> numbers(n+1, true);
vector<int> result;
int i = 2;
while(i <= n){
if(numbers[i]){
result.push_back(i);
int j = 2 * i;
while(j <= n){
numbers[j] = false;
j += i;
}
}
++i;
}
return result;
}
vector<int> prime_terms(int n, vector<int> primes = vector<int>()){
if(primes.empty()){
primes = sieve(n);
}
vector<int> result;
for(int p : primes){
if(p > n){
break;
}
if(n % p == 0){
result.push_back(p);
while(n % p == 0){
n /= p;
}
}
}
return result;
}
int main(){
cout << "Hello this is Patrick" << endl;
auto start = chrono::high_resolution_clock::now();
vector<float> n_phi(MAX + 1, 0);
auto primes = sieve(MAX);
for(auto p : primes){
n_phi[p] = 1 + 1 / ((float)p - 1);
}
int n_max = 0;
float n_phi_max = 0;
for(size_t i = 2; i < n_phi.size(); ++i){
if(n_phi[i] == 0){
auto terms = prime_terms(i, primes);
float acc = 1;
for(int t : terms){
acc *= n_phi[t];
}
n_phi[i] = acc;
if(n_phi_max < acc){
n_max = i;
n_phi_max = acc;
}
}
// cout << i << " " << n_phi[i] << endl;
}
cout << n_max << endl;
auto duration = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start);
cout << (float)duration.count()/1000 << endl;
return 0;
}