Cod sursa(job #2045761)

Utilizator SoranaAureliaCatrina Sorana SoranaAurelia Data 22 octombrie 2017 20:25:21
Problema Suma si numarul divizorilor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.17 kb
/**
Un mod mai eficient de calculare a numauluide diizori si a sumei divizoilor este
folosindu-ne de aritmtica modulara si ridicareea la putere in timp logaitmic
Astfel:


- formam ciurul si simultan sirul care contine numerele prime a BINE

Pentru ficare numar vom calcula:
-numarul de divizori(mod normal) BUN;
-suma o vom calcula dupa formula, folosindu-ne de ridicare la putere in timp logaritmic a
lui a^n si invesul modular al numarului a-1; unde a este divizorul prim si n este exponentul
acestuia

***/


#define MOD 9973
#include <cstdio>

using namespace std;
char c[1000005];
int a[7850000];
void formam_ciurul()
{
    for(int i=2;i<=1000000;i++)
    {
        if(c[i]==0)
        {
            for(int j=i*2;j<=1000000;j+=i)
                c[j]=1;
            a[++a[0]]=i;
        }
    }
}

int putere(int baza, int exponent)
{
    int rezultat=1;
    while(exponent)
    {
        if(exponent%2==1)
        {
            exponent--;
            rezultat=rezultat*baza;
        }
        exponent/=2;
        baza=baza*baza;
    }
    return rezultat;
}

void invers_modular(int a, int b, int &x, int &y)
{
    if(b!=0)
    {
        x=1;
        y=0;
        return;
    }
    int x1, y1;
    invers_modular(b,a%b,x1,y1);
    x=y1;
    y=x1-(a/b)*y1;
}
int x, y;
int main()
{
    freopen("ssnd.in", "r", stdin);
    freopen("ssnd.out", "w", stdout);
    formam_ciurul();
    int n, x;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        float s=1;
        scanf("%d", &x);
        int nrdiv=1;
        int sumasus=1;
        int sumajos=1;
        for(int d=1; a[d]<=x; d++)
            if(x%a[d]==0)
            {
                int e=0;
                while(x%a[d]==0)
                {
                    e++;
                    x=x/a[d];
                }
                nrdiv=(nrdiv*(e+1));
                sumasus=(sumasus*(putere(a[d],e+1)-1))%MOD;
                sumajos=(sumajos*(a[d]-1))%MOD;
            }
       // invers_modular(sumajos, MOD, x, y);
       // while(x<0)
       //     x+=MOD;
        printf("%d %d \n", nrdiv, (sumasus/sumajos)%MOD);
    }
    return 0;
}