poj1845

题意:求a^b的所有约数的和对9901取余。

分析:我们转化为a^b的所有质因子的等比数列的成积,例如100^1,转化为(1+2+4) * (1 + 5 + 25)。由于a^b的质因子与a的质因子相同,只是每个的数量是a的质因子的b倍。具体做法是先求所有素数,求a的所有质因子,对于每个质因子求num[i]*b+1项的等比数列。并求乘积。

View Code
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
#include
< cmath >
using namespace std;

#define maxn 10000
#define w 9901

int a, b;

bool is [maxn];
int prm[maxn];
int fac[maxn], num[maxn];

int getprm( int n)
{
int i, j, k = 0 ;
int s, e = ( int ) (sqrt( 0.0 + n) + 1 );
memset(
is , 1 , sizeof ( is ));
prm[k
++ ] = 2 ;
is [ 0 ] = is [ 1 ] = 0 ;
for (i = 4 ; i < n; i += 2 )
is [i] = 0 ;
for (i = 3 ; i < e; i += 2 )
if ( is [i])
{
prm[k
++ ] = i;
for (s = i * 2 , j = i * i; j < n; j += s)
is [j] = 0 ;
}
for (; i < n; i += 2 )
if ( is [i])
prm[k
++ ] = i;
return k;
}

int power( int a, int n)
{
int ret = 1 ;
int m = a % w;
while (n)
{
if ( 1 & n)
ret
*= m;
ret
%= w;
n
>>= 1 ;
m
*= m;
m
%= w;
}
return ret;
}

int cal( int d, int num)
{
d
%= w;
if (num == 0 )
return 1 ;
if (num == 1 )
{
return (d + 1 ) % w;
}
int mid;
if (num & 1 )
{
mid
= power(d, num / 2 + 1 );
return (mid + 1 ) * cal(d, num / 2 ) % w;
}
int x = power(d, num / 2 );
mid
= power(d, num / 2 + 1 );
return ((mid + 1 ) * cal(d, num / 2 - 1 ) + x) % w;
}

int main()
{
// freopen("t.txt", "r", stdin);
scanf( " %d%d " , & a, & b);
int n = getprm( int (sqrt(a)) + 1 );
int temp = 0 ;
for ( int i = 0 ; i < n; i ++ )
if (a % prm[i] == 0 )
{
fac[temp]
= prm[i];
while (a % prm[i] == 0 )
{
a
/= prm[i];
num[temp]
++ ;
}
temp
++ ;
}
n
= temp;
int ans = 1 ;
for ( int i = 0 ; i < n; i ++ )
ans
= ans * cal(fac[i], num[i] * b) % w;
if (a != 1 )
ans
= ans * cal(a, b) % w;
printf(
" %d\n " , ans);
return 0 ;
}

你可能感兴趣的:(poj)