Cod sursa(job #2756470)

Utilizator ptlsebiptl sebi ptlsebi Data 31 mai 2021 20:48:30
Problema Suma si numarul divizorilor Scor 70
Compilator c-64 Status done
Runda Arhiva educationala Marime 2.8 kb
#include <stdio.h>
#include <stdint.h>
#include <math.h>

void read_uint32_t(FILE *__restrict stream, uint32_t *__restrict nr) {
    uint8_t ch;
    *nr = 0;
    while ((ch = fgetc(stream)) && ('0' <= ch && ch <= '9')) {
        *nr *= 10;
        *nr += ch - '0';
    }
    if (ch == '\r') {
        fgetc(stream);
    }
}

void read_uint64_t(FILE *__restrict stream, uint64_t *__restrict nr) {
    uint8_t ch;
    *nr = 0;
    while ((ch = fgetc(stream)) && ('0' <= ch && ch <= '9')) {
        *nr *= 10;
        *nr += ch - '0';
    }
    if (ch == '\r') {
        fgetc(stream);
    }
}

#define P10_6 1000000
#define MOD 9973

typedef uint8_t bitset;

uint32_t primes[78499];
uint32_t pc = 0;

uint64_t power(uint64_t a, uint64_t b) {
    uint64_t res = 1;
    a %= MOD;
    while (b) {
        if (b & 1) {
            res = (res * a) % MOD;
        }
        b >>= 1;
        a = (a * (a % MOD)) % MOD;
    }
    return res;
}

void bits_set(bitset *bits, uint64_t x) {
    bits[x / 8] |= (1 << (x % 8));
}

bitset bits_get(const bitset *bits, uint64_t x) {
    return (bits[x / 8] >> (x % 8)) & 1;
}

void mk_ciur() {
    bitset ciur[125001] = {0};
    uint64_t i, j;
    primes[0] = 2;
    ++pc;
    for (i = 4; i <= P10_6; i += 2) {
        bits_set(ciur, i);
    }
    for (i = 3; i <= P10_6; i += 2) {
        if (!bits_get(ciur, i)) {
            primes[pc] = i;
            ++pc;
            for (j = i * i; j <= P10_6; j += i) {
                bits_set(ciur, j);
            }
        }
    }
}

uint32_t inv[MOD];

void invers_mod() {
    int32_t i;
    for (i = 1; i < MOD; ++i) {
        inv[i] = power(i, MOD - 2);
    }
}

int main() {
    mk_ciur();
    invers_mod();


    uint32_t n;
    uint64_t x;
    uint64_t sx;
    uint64_t nrd = 1, sumd = 1, p = 0, num;

    {
        FILE *__restrict in = fopen("ssnd.in", "r");
        FILE *__restrict out = fopen("ssnd.out", "w");

        read_uint32_t(in, &n);
        while (n > 0) {
            read_uint64_t(in, &x);
            sx = (uint64_t) sqrt(x);

            {
                nrd = sumd = 1;
#define di primes[i]
                int32_t i;
                for (i = 0; (uint64_t) di <= sx && i < pc; ++i) {
                    p = 0;
                    while ((x % di) == 0) {
                        ++p;
                        x /= di;
                    }
                    nrd *= (p + 1);
                    sumd *= (power(di, p + 1) + MOD - 1);
                    num = (di - 1) % MOD;
                    sumd *= inv[num];
                    sumd %= MOD;
                }
#undef di
            }
            if (x != 1) {
                nrd *= 2;
                sumd *= (x + 1);
                sumd %= MOD;
            }

            fprintf(out, "%llu %llu\n", nrd, sumd);

            --n;
        }
        fclose(in);
        fclose(out);
    }

    return 0;
}