Cod sursa(job #1480106)

Utilizator salam1Florin Salam salam1 Data 2 septembrie 2015 05:23:04
Problema Suma si numarul divizorilor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.45 kb
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
const int NMAX = 1000505;
const int MOD = 9973;

struct primeFactorInfo {
  ll p, overAll;
  int exp;
};

int tests, r, invMod[MOD], E2[MOD];
ll n, P[NMAX];
bool notPrime[NMAX];

struct solution {
  ll noDivs, sumDivs;
};

int lgput(int base, int exp, int mod) {
  int res = 1;
  while (exp) {
    if (exp & 1) {
      res = (res * base) % mod;
    }
    base = (base * base) % mod;

    exp >>= 1;
  }
  return res;
}

int gcd(int x, int y) {
  return !y ? x : gcd(y, x % y);
}

void prepare() {
  for (int i = 2; i * i < NMAX; i++)
    if (!notPrime[i]) {
      for (int j = i * i; j < NMAX; j += i)
        notPrime[j] = 1;
    }

  for (int i = 2; i < NMAX; i++)
    if (!notPrime[i])
      P[++r] = i;

  //printf("IS PRIME ? %d\n", notPrime[MOD]);
  int mark[MOD] = {0};

  E2[0] = 1;
  for (int i = 1; i < MOD; i++) {
    E2[i] = E2[i - 1] * 2;
    if (E2[i] >= MOD) E2[i] -= MOD;
    /*if (mark[E2[i]] && i <= 5000) {
      printf("WTF %d SAME AS %d\n", i, mark[E2[i]]);
    }*/
    mark[E2[i]] = i;
  }
  //printf("%d %d %d\n", E2[3324], lgput(2, 3324, MOD), gcd(3324, MOD));

  for (int i = 1; i < MOD; i++) {
    invMod[i] = lgput(i, MOD - 2, MOD);
  }
}

vector<primeFactorInfo> decompose(ll n) {
  vector<primeFactorInfo> sol;
  for (int i =  1; 1LL * P[i] * P[i] <= n; i++)
    if (n % P[i] == 0) {
      int exp = 0;
      ll overAll = 1;
      while (n % P[i] == 0) {
        n /= P[i];
        overAll = (overAll * (P[i] % MOD)) % MOD;;
        exp++;
      }
      sol.push_back({P[i] % MOD, overAll, exp});
    }
  if (n != 1) {
    sol.push_back({n % MOD, n % MOD, 1});
  }

  return sol;
}

solution computeSol(vector<primeFactorInfo>& divs) {
  if (divs.size() == 0) {
    return {1, 1};
  }
  int res = 1;
  ll noDivs = 1;
  for (auto& div: divs) {
    ll denom = (div.overAll * div.p) % MOD - 1;
    if (denom < 0) denom += MOD;
    ll nom = div.p - 1;
    if (nom < 0) nom += MOD;

    res = (res * (denom * invMod[nom]) % MOD) % MOD;
    //printf("%lld %d %lld %d\n", div.p, div.exp, nom, res);
    noDivs *= (div.exp + 1);
  }

  return {noDivs, res};
}

void solve() {
  scanf("%d", &tests);
  while (tests--) {
    scanf("%lld", &n);

    vector<primeFactorInfo> divs = decompose(n);
    solution sol = computeSol(divs);
    printf("%lld %lld\n", sol.noDivs, sol.sumDivs);
  }
}

int main() {
  freopen("ssnd.in", "r", stdin);
  freopen("ssnd.out", "w", stdout);

  prepare();
  solve();
  return 0;
}