您的位置:首页 > 其它

POJ 1845 Sumdiv

2013-12-28 21:51 393 查看
超时超时一定要注意不要超时啊!!

题目大意:

给两个数a,b,求a的b次方的所有约数的和对9901取余的值。

解题思路:

a可以分解成多个素数相乘的的形式,这些素数可能有些相同,所以就成了以下形式:

a=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)



其中pi为素数,因为有可能相同例如8=2^3,所以写成了pi的ki次方形式。

a的约数之和就是:

(1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... (1+pn+pn^2+pn^3+...pn^kn)

那么a的b次方的约数之和就是:

[1+p1+p1^2+...+p1^(k1*b)] * [1+p2+p2^2+...+p2^(k2*b)] *...* [1+pn+pn^2+...+pn^(kn*b)]



只需要快速的实现这一些计算就能过。

需要注意的是:

1、经过测试,后台数据每个文件只有一组数据,也就是说代码中不需要写以文件结尾。但是数据文件有多个,

这也就是说每测试一组数据后台都要重跑一边代码。打素数表来生成素数的解题方式不适用于这样的测试方式

需要用更高效的方法来生成素数。

代码中用的方法:

首先对2进行特殊处理,因为除了2之外的所有偶数都不是素数,

i从3开始循环,每次加2对a取余,判断是否整除。如果能整除,一直除到不能整除。

如果这个数是合数,一定不会整除a,因为如果那样的话,他的质因数就可以整除a,就没除干净,这是不可能的,所以每次操作一定是素数的操作。

2、对于处理pi的ki*b次方不能枚举ki*b次,因为ki*b用可能是一个10的10次方以上的数,那样的话单这一次就超时了。需要用另一种方法,我们来举个例子:

2的4次方可以转化成4的2次方,2的5次方可以转化成4的2次方成2。


具体实现见代码。

3、处理[1+p1+p1^2+...+p1^(k1*b)] 也不能枚举指数,同前面第二条的原因是一样的。我们需要这样解决:

对于n项1+p1+p1^2+...+p1^n来说,

当n是偶数时: (1
+ p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);对于前面的 (1 + p + p^2 +...+ p^(n/2-1)) 还可以继续递归计算。

当n是奇数时:(1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1));对于前面的 (1
+ p + p^2 +...+ p^(n/2)) 还可以继续递归计算。


4、运算过程中用longlong,对a的值为0,1,b的值为1,进行特判减少运算,运算过程中用同余模定理控制运算中变量数值的大小。

下面是代码:

#include <stdio.h>
#define N 10000000
int noc=0;
struct node
{
int x,y;
} node[10000];
long long power(long long p,long long n)
{
long long yu=1;
while(n)
{
if(n%2)
yu=(yu*p)%9901;
n/=2;
p=(p*p)%9901;
}
return yu;
}
long long sum(long long p,long long n)
{
if(n==0)
{
return 1;
}
if(n%2)
{
return sum(p,n/2)*(1+power(p,n/2+1))%9901;
}
else
{
return (sum(p,n/2-1)*(1+power(p,n/2+1))+power(p,n/2))%9901;
}
}
int main()
{
int a,b,in=0,ans=1;
scanf("%d%d",&a,&b);
if(a == 0)
{
puts("0");
return 0;
}
if(b == 0 || a == 1)
{
puts("1");
return 0;
}
for(int i=2; i*i<=a;)
{
if(a%i==0)
{
node[noc].x=i;
node[noc].y=0;
while(a%i==0)
{
node[noc].y++;
a/=i;
}
noc++;
}
if(i==2)
i++;
else
i+=2;
}
if(a!=1)
{
node[noc].x=a;
node[noc].y=1;
noc++;
}
for(int i=0; i<noc; i++)
{
ans=(ans*sum(node[i].x,node[i].y*b))%9901;
}
printf("%d\n",ans);
return  0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: