Finished 070, by using the way quicker prime factorization it is done in 18 seconds

This commit is contained in:
2021-11-14 22:25:02 +01:00
parent 673b908d16
commit 20237a22af

103
projecteuler/070/main.cpp Normal file
View File

@@ -0,0 +1,103 @@
/*
Totient permutation
Euler's Totient function, φ(n) [sometimes called the phi function], is used to determine the number of positive numbers less than or equal to 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.
The number 1 is considered to be relatively prime to every positive number, so φ(1)=1.
Interestingly, φ(87109)=79180, and it can be seen that 87109 is a permutation of 79180.
Find the value of n, 1 < n < 107, for which φ(n) is a permutation of n and the ratio n/φ(n) produces a minimum.
*/
#include <bits/stdc++.h>
using namespace std;
const int MAX = pow(10, 7);
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> result;
if(n % 2 == 0){
result.push_back(2);
while(n % 2 == 0){
n /= 2;
}
}
for(int i = 3; i <= sqrt(n); i += 2){
if(n % i == 0){
result.push_back(i);
while(n % i == 0){
n /= i;
}
}
}
if(n > 2){
result.push_back(n);
}
return result;
}
int main(){
cout << "Hello this is Patrick" << endl;
auto start = chrono::high_resolution_clock::now();
int n_min = 0;
float min_ratio = 2;
for(int n = 2; n < MAX; ++n){
auto terms = prime_terms(n);
float phi = n;
for(float term : terms){
phi *= 1.0 - 1.0 / term;
}
int p = phi;
string s_phi = to_string(p), s_n = to_string(n);
sort(s_phi.begin(), s_phi.end());
sort(s_n.begin(), s_n.end());
if(s_phi == s_n){
if((float)n / phi < min_ratio){
min_ratio = (float)n / phi;
n_min = n;
}
}
}
cout << n_min << endl;
auto duration = chrono::duration_cast<chrono::milliseconds>(chrono::high_resolution_clock::now() - start);
cout << (float)duration.count()/1000 << endl;
return 0;
}