Cod sursa(job #2835292)

Utilizator ciprian.morosanuCiprian Morosanu ciprian.morosanu Data 18 ianuarie 2022 14:30:18
Problema Fractii Scor 80
Compilator c-64 Status done
Runda Arhiva de probleme Marime 7.92 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

long long v1(int n) {
    long long fractionsCount = 0;
    for (int a = 1; a <= n; ++a) {
        int count = 0;
        for (int b = 1; b <= n; ++b) {
            if (gcd(a, b) == 1) {
                fractionsCount++;
                count++;
            }
        }
        if (a > 1 && n == 36) {
//            printf("%d ", count);
        }
    }
    if (n == 36) {
//        printf("\n");
    }
    return fractionsCount;
}

long long v2(int n) {
    if (n == 1) {
        return 1;
    }
    long long fractionsCount = n;
    int primeDivisors[8];
    int primeDivisorsCount = 0;
    int *array = calloc(n, sizeof(int));
    for (int num = 2; num <= n; ++num) {
        primeDivisorsCount = 0;
        int clone = num;
        if (clone % 2 == 0) {
            primeDivisors[primeDivisorsCount++] = 2;
            do {
                clone >>= 1;
            } while (clone % 2 == 0);
        }
        for (int div = 3; div <= clone; div += 2) {
            if (clone % div == 0) {
                primeDivisors[primeDivisorsCount++] = div;
                do {
                    clone /= div;
                } while (clone % div == 0);
            }
        }
        switch (primeDivisorsCount) {
            case 0:
                fractionsCount += n - n / num;
                break;
            case 1:
                fractionsCount += n - n / primeDivisors[0];
                break;
            case 2:
                fractionsCount +=
                        n - (n / primeDivisors[0] + n / primeDivisors[1] - n / (primeDivisors[0] * primeDivisors[1]));
                break;
            default: {
                memset(array, 0, n * sizeof(int));
                for (int index = 0; index < primeDivisorsCount; ++index) {
                    for (int i = primeDivisors[index]; i <= n; i += primeDivisors[index]) {
                        array[i - 1] = 1;
                    }
                }
                for (int index = 0; index < n; ++index) {

                    if (array[index] == 0) {
                        fractionsCount++;
                    }
                }
            }
                break;
        }
    }
    free(array);
    return fractionsCount;
}

int *getPrimeNumbersUntil(int n) {
    int *array = (int *) calloc(n + 1, sizeof(int));
    for (int i = 2; i <= n; ++i) {
        if (array[i] == 0) {
            for (int j = 2 * i; j <= n; j += i) {
                array[j] = 1;
            }
        }
    }
    return array;
}

int computeCombinationSum(int *divisors, int divisorsCount) {
    int sum = -1;
    int value = divisorsCount - 2;
    for (int i = 1; i <= value; ++i) {
        switch (i) {
            case 1:
                for (int index = 0; index < divisorsCount; ++index) {
                    sum += divisors[index];
                }
                break;
            default:
                sum = -1;
        }
    }
    return sum;
}

long long v3(int n) {
    if (n == 1) {
        return 1;
    }
    int *primeNumbers = getPrimeNumbersUntil(n);
    long long fractionsCount = n;
//    long long oldFraction = fractionsCount;
    int primeDivisors[8];
    int divisorStats[15] = {0};
    int primeDivisorsCount = 0;
    int *array = calloc(n, sizeof(int));
    for (int num = 2; num <= n; ++num) {
        primeDivisorsCount = 0;
        if (primeNumbers[num] == 1) {
            int clone = num;
            for (int div = 2; div <= clone; ++div) {
                if (primeNumbers[clone] == 0) {
                    primeDivisors[primeDivisorsCount++] = clone;
                    break;
                }
                if (primeNumbers[div] == 0) {
                    if (clone % div == 0) {
                        primeDivisors[primeDivisorsCount++] = div;
                        do {
                            clone /= div;
                        } while (clone % div == 0);
                    }
                }
            }
        }
        int divisorsProduct = 1;
        for (int i = 0; i < primeDivisorsCount; ++i) {
            divisorsProduct *= primeDivisors[i];
        }
        divisorStats[primeDivisorsCount]++;
        switch (primeDivisorsCount) {
            case 0:
                fractionsCount += n - n / num;
                break;
            case 1:
                fractionsCount += n - n / primeDivisors[0];
                break;
            case 2:
                fractionsCount +=
                        n - (n / primeDivisors[0] + n / primeDivisors[1] - n / (primeDivisors[0] * primeDivisors[1]));
                break;
            case 3:
                fractionsCount +=
                        n - (
                                n / primeDivisors[0] +
                                n / primeDivisors[1] +
                                n / primeDivisors[2] -
                                (
                                        n / (primeDivisors[0] * primeDivisors[1]) +
                                        n / (primeDivisors[0] * primeDivisors[2]) +
                                        n / (primeDivisors[1] * primeDivisors[2]) -
                                        n / (primeDivisors[0] * primeDivisors[1] * primeDivisors[2])
                                )
                        );
                break;
            default: {
                memset(array, 0, n * sizeof(int));
                for (int index = 0; index < primeDivisorsCount; ++index) {
                    for (int i = primeDivisors[index]; i <= n; i += primeDivisors[index]) {
                        array[i - 1] = 1;
                    }
                }
                for (int index = 0; index < n; ++index) {

                    if (array[index] == 0) {
                        fractionsCount++;
                    }
                }
            }
                break;
        }
        if (n == 36) {
//            printf("%d ", fractionsCount - oldFraction);
        }
//        oldFraction = fractionsCount;
    }
    if (n == 36) {
//        printf("\n");
    }
//    for (int i = 0; i < 15; ++i) {
//        printf("%d : %d\n", i, divisorStats[i]);
//    }
    free(array);
    free(primeNumbers);
    return fractionsCount;
}

long long v4(int n) {
    if (n == 1) {
        return 1;
    }
    int *primeNumbers = getPrimeNumbersUntil(n);
    long long fractionsCount = 1;
    int primeDivisors[8];
    int primeDivisorsCount = 0;
    for (int num = 2; num <= n; ++num) {
        primeDivisorsCount = 0;
        if (primeNumbers[num] == 1) {
            int clone = num;
            for (int div = 2; div <= clone; ++div) {
                if (primeNumbers[clone] == 0) {
                    primeDivisors[primeDivisorsCount++] = clone;
                    break;
                }
                if (primeNumbers[div] == 0) {
                    if (clone % div == 0) {
                        primeDivisors[primeDivisorsCount++] = div;
                        do {
                            clone /= div;
                        } while (clone % div == 0);
                    }
                }
            }
        } else {
            primeDivisors[primeDivisorsCount++] = num;
        }
        int product = 1;
        int divProduct = 1;
        for (int i = 0; i < primeDivisorsCount; ++i) {
            product *= primeDivisors[i] - 1;
            divProduct *= primeDivisors[i];
        }
        fractionsCount += 2 * num / divProduct * product;
    }
    free(primeNumbers);
    return fractionsCount;
}

int main() {
    char *inFileName = "fractii.in";
    char *outFileName = "fractii.out";
    FILE *in = fopen(inFileName, "r");
    if (in == NULL) {
        printf("Cannot open %s.\n", inFileName);
        return 1;
    }
    FILE *out = fopen(outFileName, "w");
    int n;
    fscanf(in, "%d", &n);
    if (n == 1) {
        fprintf(out, "1");
    } else {
        fprintf(out, "%lld\n", v4(n));
    }
    fclose(in);
    fclose(out);
    return 0;
}