Cod sursa(job #993599)

Utilizator BeilandArnoldArnold Beiland BeilandArnold Data 4 septembrie 2013 09:59:26
Problema Suma si numarul divizorilor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.12 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 getmodinv(unsigned a){
    int x,y;
    euclid_extins(&x,&y,a,MODULO);
    while(x<0) x+=MODULO;
    return x;
}

unsigned modexp(unsigned long long 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 long long p,unsigned d,const vector<unsigned> &modinvs){
    *nrdiv = (*nrdiv) * (d+1) % MODULO;
    unsigned me=modexp(p,d+1);
    if(me==0) me=MODULO-1;
    else --me;
    *sumdiv = *sumdiv * me * modinvs[(p-1)/2] %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);

    vector<unsigned> modinvs(MODULO/2+1);
    modinvs[0]=1;
    for(unsigned i=2;i<=MODULO;i+=2) modinvs[i/2]=getmodinv(i);

    while(t--){
        unsigned long long n; fin>>n;
        unsigned nrdiv=1,sumdiv=1;

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

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