您的位置:首页 > 其它

POJ 1845 数论

2016-01-21 20:28 190 查看
Sumdiv

Time Limit: 1000MS Memory Limit: 30000K

Total Submissions: 17214 Accepted: 4320

Description

Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).

Input

The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.

Output

The only line of the output will contain S modulo 9901.

Sample Input

2 3

Sample Output

15

Hint

2^3 = 8.

The natural divisors of 8 are: 1,2,4,8. Their sum is 15.

15 modulo 9901 is 15 (that should be output).

题意:

问a^b的所有的因子数求和再模上9901结果是多少。

题解:

个人觉得是比较综合的数论题目了。里面涉及的知识点有:

1.一个数可以写成素数幂的形式,如a = p1^k1*p2^k2*p3^k3……pn^kn

2.求一个数的幂可以用二进制的思想来想以加速运算,即快速幂算法。具体为求a^n,如果n为奇数,则a^n = a^(n/2)*a^(n/2)*a.n为偶数则为a^n = a^(n/2)*a^(n/2),则递归下去就可以解决,时间复杂度为O(logn)

3**对形如1+q+q^2……q^n的等比数列求和,我们自然想到的求和公式(1-q^n)/(1-q),但是在模运算中是没有除法的同余模的。其次我们在计算q^n时即使用上快速幂也是O(logn)的复杂度。但是我们有另外一个方法,当n为奇数时1+q+q^2……q^n=(1+q+q^2……q^n/2)(1+q^(n/2+1)),当n为偶数为1+q+q^2……q^n=(1+q+q^2……q^(n/2-1))(1+q^(n/2+1)+q^n/2)如此我们就能递归解决了,这个算法的复杂度也是O(logn),和用公式的复杂度是一样的。**

有了这些前置知识点我们再来做这题,首先我们把a拆成素数幂的形式:

a = p1^k1*p2^k2*p3^k3……pn^kn,这里我们用开根号法来求。

接着a^b = p1^bk1*p2^bk2*p3^bk3……pn^bkn

我们知道a^b的所有和数必然是由p1,p2……pn乘上合适的幂组合成的,那么我们每个素数因子都分别 不取,取pi,取pi^2……取pi^bki再组合起来就是总和。

数学表达式为:

sum = (1+ p1 + p1^2 ……p1^(b*k1))*(1+ p2 + p2^2 ……p2^(b*k2))……

然后用上同余模定理就可以解出来了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#define f(i,a,b) for(i = a;i<=b;i++)
#define fi(i,a,b) for(i = a;i>=b;i--)

using namespace std;
#define SIZE 50000000
#define MOD 9901

struct Po{
long long pre;
long long k;
};

long long mod_pow(long long x,long long n){
long long res = 1;
while(n>0){
if(n&1) res=res*x%MOD;
x = x*x%MOD;
n>>=1;
}
return res;
}

long long SUM(long long q,long long n){
if(n==0)
return 1;
if(n&1)
return (SUM(q,n/2)*(1+mod_pow(q,n/2+1)))%MOD;
else
return (SUM(q,n/2-1)*(1+mod_pow(q,n/2+1))+mod_pow(q,n/2))%MOD;
}

int main()
{
long long a,b;
while(~scanf("%lld%lld",&a,&b)){
int i;

queue<Po>qu;
for(i = 2;i*i<a;){
int k = 0;
if(a%i==0){
while(a%i==0){
k++;
a/=i;
}
Po tem;
tem.pre = i;
tem.k = k;
qu.push(tem);
}
i==2?i++:i+=2;
}
if(a>1){
Po tem;
tem.pre = a;
tem.k = 1;
qu.push(tem);
}
long long sum = 1;
while(!qu.empty()){
Po tem = qu.front();qu.pop();
sum = (sum*SUM(tem.pre,tem.k*b))%MOD;
}
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj