Cod sursa(job #293339)

Utilizator ScrazyRobert Szasz Scrazy Data 1 aprilie 2009 16:48:02
Problema Suma divizorilor Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.35 kb
#include <cstdio>

long a, b;

int mod(long a) //a mod 9901
{ 
    int res = a % 9901;
    while (res < 0) res += 9901;
    return res;
}

int put(long a, long b) //a - t b -re emeli mod 9901
{
    if (b == 0) return 1;
    int aux = mod(put(a, b >> 1)); //a^[b/2]
    int res = mod(aux*aux);
    if (b & 1)
	res = mod(res * a);
    return res;
}

void cmmdc(long a, long b, int &x, int &y)
{
    if (b == 0)
    {
	x = 1;
	y = 0;
	return ; //a divisor commun
    } 
    int x0, y0;
    cmmdc(b, a % b, x0, y0);
    x = y0;
    y = x0 - (a / b) * y0;
}

int invers(long a)
{
    int x, y; 
    cmmdc(a, 9901, x, y);
    return mod(x);
}

int progresie(long a, long b) //(1 + a + a^2 + ... + a ^ b)
{
    if (a == 1) return b + 1; 
    int a1 = mod(put(a, b + 1) - 1); 
    int a2 = mod(invers(a - 1));
    return mod(a1 * a2);
}

void solve(long a, long b)
{
    long res = 0, p = 0;
    while (a % 2 == 0)
    {
	p++; 
	a /= 2;
    }
    res = progresie(2, p * b);
    
    for (int i = 3; i * i <= a; ++i)
    {
	if (a % i) continue;
	p = 0;
	while (a % i == 0)
	{
	    p++;
	    a /= i;
	}
	res = mod(res * progresie(mod(i), p * b));
    }
    if (a > 1)
	res = mod(res * progresie(mod(a), b));
    
    printf("%ld\n", res);
}

int main()
{
    freopen("sumdiv.in","r",stdin);
    freopen("sumdiv.out","w",stdout);
    scanf("%ld%ld", &a, &b);
    solve(a, b);

    return 0;
}