Cod sursa(job #993594)

Utilizator BeilandArnoldArnold Beiland BeilandArnold Data 4 septembrie 2013 09:25:55
Problema Suma si numarul divizorilor Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 1.9 kb
#include <fstream>
#include <vector>
#include <cmath>
using std::vector;
using std::sqrt;

const int NR_PRIMES_BELOW_ONE_MILION=78498;
const int MODULO=9973;

void euclid_extins(int *x,int *y,int a, int b){
    if(b==0){ *x=1; *y=0; }
    else{
        int x0,y0,c=a/b;
        euclid_extins(&x0,&y0,b,a%b);
        *x=y0;
        *y=x0-c*y0;
    }
}

unsigned modinv(unsigned a){
    int x,y;
    euclid_extins(&x,&y,a,MODULO);
    while(x<0) x+=MODULO;
    return x;
}

unsigned modexp(unsigned base, unsigned exp){
    if(exp==0) return 1;
    else if(exp==1) return base%MODULO;
    else{
        unsigned x=modexp(base,exp>>1);
        if(exp&1) return ((base%MODULO)*x*x)%MODULO;
        else return x*x%MODULO;
    }
}

void addf(unsigned *nrdiv, unsigned *sumdiv, unsigned p, unsigned d){
    *nrdiv = (*nrdiv) * (d+1) % MODULO;
    unsigned k=( ((MODULO+modexp(p,d+1)-1)%MODULO) * modinv(p-1) )%MODULO;
    *sumdiv = *sumdiv * k %MODULO;
}

void calc_primes(vector<unsigned> &primes,unsigned limit){
    primes[0]=2;
    unsigned c=1;
    vector<bool> ciur(500000,true);
    ciur[0]=false;
    for(unsigned i=3;i<limit;i+=2)
        if(ciur[i>>1]){
            primes[c++]=i;
            for(unsigned j=3;j*i<limit;j+=2) ciur[(i*j)>>1]=false;
        }
}

int main(){
    std::ifstream fin("ssnd.in");
    std::ofstream fout("ssnd.out");

    short t;
    fin>>t;
    vector<unsigned> primes(NR_PRIMES_BELOW_ONE_MILION);
    calc_primes(primes,1000000);

    while(t--){
        unsigned n; fin>>n;
        unsigned sqrtn=std::sqrt(n);
        unsigned nrdiv=1,sumdiv=1;

        unsigned p;
        for(unsigned i=0;(p=primes[i])<=sqrtn;++i){
            unsigned d=0;
            while(n%p==0){ ++d; n/=p; }
            if(d>0) addf(&nrdiv,&sumdiv,p,d);
        }
        if(n>1) addf(&nrdiv,&sumdiv,n,1);

        fout<<nrdiv<<' '<<sumdiv<<'\n';
    }
}