Cod sursa(job #833173)

Utilizator BlaugranasEnal Gemaledin Blaugranas Data 11 decembrie 2012 23:30:04
Problema Suma divizorilor Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.66 kb
#include <stdio.h>

long A, B, S;

void CitesteDate(void){
  FILE *f=fopen("SUMDIV.IN","rt");
  fscanf(f,"%ld%ld",&A,&B);
  fclose(f);
}

inline int ProdusMod9901(int x, int y){
  return ((long)x * y) % 9901;
}

int RidicareLaPutereMod9901(int a, long n){
  int aux;
  if (!n)
    return 1;
  aux = RidicareLaPutereMod9901(a, n >> 1); // a^[n/2];
  aux = ProdusMod9901(aux, aux); // a^([n/2]*2)
  if (n&1)                       // daca e impar
    aux = ProdusMod9901(aux, a); // mai trebuie o inmultire
  return aux;
}

int InversMod9901(int a){
  // determina b astfel incat a * b % 9901 = 1;
  if (!a)
    return 0;
  long rez = 1;
  while (rez % a)
    rez += 9901;
  return rez / a;
}

int ProgresieMod9901(int q, long exp){
  // calculeaza valoarea (1 + q^1 + q^2 + ... + q^exp) % 9901
  if (q == 1)
    return (exp + 1) % 9901;
  else
    return ProdusMod9901((RidicareLaPutereMod9901(q, exp+1)+9900)%9901, // (q^(exp+1) - 1) % 9901 ; -1 = 9900 (mod 9901)
			 InversMod9901((q+9900)%9901)); // q - 1 = q + 9900 (mod 9901)
}

void DeterminaSolutia(void){
  // puterea lui 2
  int p = 0;
  while (!(A & 1)){
    p++;
    A >>= 1;
  }
  S = ProgresieMod9901(2, p * B);
  // celelalte puteri
  for (int i = 3; (long)i*i<=A; i+=2)
    if (!(A%i)){
      p = 0;
      while (!(A%i)){
	p++;
	A/=i;
      }
      S = ProdusMod9901(S, ProgresieMod9901(i%9901, p*B));
    }
  if (A > 1)
    S = ProdusMod9901(S, ProgresieMod9901(A%9901, B));
}

void ScrieSolutia(void){
  FILE *f=fopen("SUMDIV.OUT","wt");
  fprintf(f,"%ld\n",S);
  fclose(f);
}

int main(void){
  CitesteDate();
  DeterminaSolutia();
  ScrieSolutia();
}