Pagini recente » Cod sursa (job #1203244) | Cod sursa (job #2875600) | Cod sursa (job #2644398) | Cod sursa (job #2801160) | Cod sursa (job #2244698)
#include <fstream>
using namespace std;
ifstream in("fractii.in");
ofstream out("fractii.out");
const int N_MAX = 1000000;
int totient[N_MAX + 1]; //indicatorul lui Euler
///O(N*logN)
void compute_totient(int N) {
// initializare
totient[1] = totient[2] = 1;
for(int i = 3; i <= N; i++)
totient[i] = i - 1;
/**
TEOREMA
---------------------------------------
n = suma tuturor totient(d), unde d | n
*/
// folosim ideea de la ciur si teorema precedenta:
for(int i = 2; i <= N; i++) //deja stim valoarea totient[1...i]
for(int j = 2 * i; j <= N; j += i) //scadem pe totient[i] din totient[k * i]
totient[j] -= totient[i];
}
///O(NloglogN)
void compute_totient2(int N) {
// initializare
for(int i = 1; i <= N; i++)
totient[i] = i; //semnifica faptul ca nu e calculat, adica ca este prim
/**
TEOREMA
--------------------------------------------------------
n = p1 ^ a1 * p2 ^ a2 * ... * pk ^ ak
totient(n) = n * (1 - 1/p1)(1 - 1/p2) * ... * (1 - 1/pk)
*/
//folosim ideea de la ciur si teorema precedenta:
for(int i = 2; i <= N; i++)
if(totient[i] == i) //nu este calculat, deci i este prim
for(int j = i; j <= N; j += i) //iteram prin toti multiplii lui i, inclusiv i
totient[j] -= totient[j] / i;
}
int main() {
int N;
in >> N;
compute_totient2(N);
long long sol = 1;
for(int i = 2; i <= N; i++)
sol += 2 * totient[i];
out << sol;
return 0;
}