poj 1845 Sumdiv——数论

由题意,要求A^B的所有约数之和%9901。
A可以唯一分解成p1^a1*p2^a2*...*pn^an,
A^B=p1^(a1*B)*p2^(a2*B)*...*pn^(an*B);
A^B的所有约数之和=[1+p1+p1^2+...+p1^(a1*B)]*[1+p2+p2^2+...+p2^(a2*B)]*[1+pn+pn^2+...+pn^(an*B)].
而等比数列1+pi+pi^2+pi^3+...+pi^n可以由二分求得,思想是把式子从中间断开。
若n为奇数,一共有偶数项,设p为3,则(1+p)+(p^2+p^3)=(1+p)+p^2(1+p).
若n为偶数,一共有奇数项,设p为4,则(1+p)+p^2+(p^3+p^4)=(1+p)+p^2+p^3(1+p)。

参考:http://www.cppblog.com/RyanWang/archive/2009/07/19/90541.html

先开始写的total*=mod(array[i].p,(array[i].a)*b)%MOD; 把我WA惨了……改了才过的……呜呜……

1845 Accepted 400K 0MS G++ 1407B 2011-08-10 10:26:40
#include<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<algorithm>
#include
<cmath>
#define MOD 9901

struct f
{
long long p;
long long a;
};

f array[
300000+10];
long long quickmod(long long p,long long a)
{
if(a==0)
return 1;
if(a==1)
return p;
long long x=quickmod(p,a/2)%MOD;
long long ans=x*x%MOD;
if(a%2==1)
ans
=ans*p%MOD;
return ans;
}

long long mod(long long p,long long a)
{
long long total=0;
if(a==0)
return 1;
if(a==1)
return (1+p)%MOD;
if(a%2==0)
{
long long ans=mod(p,a/2-1)%MOD;
total
=(ans+(quickmod(p,a/2)%MOD)*(1+(p*ans)%MOD))%MOD;
return total;
}
else if(a%2==1)
{
long long ans=mod(p,a/2)%MOD;
total
=(ans+(quickmod(p,a/2+1)*ans)%MOD)%MOD;
return total;
}
return total;
}


int main(void)
{
long long a,b;
scanf(
"%lld %lld",&a,&b);
if(a==1)
puts(
"1");
else if(a==0)
puts(
"0");
else
{
long long i=2;
long long top=0;
while(i*i<=a)
{
if(a%i==0)
{
array[top].p
=i;
while(a%i==0)
{
a
/=i;
array[top].a
++;
}
top
++;
}
i
++;
}
if(a!=1)
{
array[top].p
=a;
array[top].a
=1;
top
++;
}
top
--;
long long total=1;
for(i=0;i<=top;i++)
{
// printf("p=%lld a=%lld\n",array[i].p,array[i].a);
total=(total*mod(array[i].p,(array[i].a)*b)%MOD)%MOD;
}
printf(
"%lld\n",total%MOD);
}
}

  


你可能感兴趣的:(div)