POJ 1845 Sumdiv(数论,求A^B的所有约数和)
Sumdiv
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 10071 | Accepted: 2357 |
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).
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
Source
题意:求 A^B的所有约数之和对9901取模后的结果.
根据唯一分解定理将A进行因式分解可得:A = p1^a1 * p2^a2 * p3^a3 * pn^an.
A^B=p1^(a1*B)*p2^(a2*B)*...*pn^(an*B);
A^B的所有约数之和sum=[1+p1+p1^2+...+p1^(a1*B)]*[1+p2+p2^2+...+p2^(a2*B)]*[1+pn+pn^2+...+pn^(an*B)].
根据唯一分解定理将A进行因式分解可得:A = p1^a1 * p2^a2 * p3^a3 * pn^an.
A^B=p1^(a1*B)*p2^(a2*B)*...*pn^(an*B);
A^B的所有约数之和sum=[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)=(1+p^2)*(1+p)
若n为奇数,一共有偶数项,设p为3,则(1+p)+(p^2+p^3)=(1+p)+p^2(1+p)=(1+p^2)*(1+p)
1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2))*(1+p^(n/2+1));
若n为偶数,一共有奇数项,设p为4,则(1+p)+p^2+(p^3+p^4)=(1+p)+p^2+p^3(1+p)=(1+p^3)*(1+p)+P^2
若n为偶数,一共有奇数项,设p为4,则(1+p)+p^2+(p^3+p^4)=(1+p)+p^2+p^3(1+p)=(1+p^3)*(1+p)+P^2
1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2-1))*(1+p^(n/2+1));
/* POJ 1845 Sumdiv 求A^B的所有约数之和%9901 */ #include<stdio.h> #include<math.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; #define MOD 9901 //****************************************** //素数筛选和合数分解 const int MAXN=10000; int prime[MAXN+1]; void getPrime() { memset(prime,0,sizeof(prime)); for(int i=2;i<=MAXN;i++) { if(!prime[i])prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++) { prime[prime[j]*i]=1; if(i%prime[j]==0) break; } } } long long factor[100][2]; int fatCnt; int getFactors(long long x) { fatCnt=0; long long tmp=x; for(int i=1;prime[i]<=tmp/prime[i];i++) { factor[fatCnt][1]=0; if(tmp%prime[i]==0) { factor[fatCnt][0]=prime[i]; while(tmp%prime[i]==0) { factor[fatCnt][1]++; tmp/=prime[i]; } fatCnt++; } } if(tmp!=1) { factor[fatCnt][0]=tmp; factor[fatCnt++][1]=1; } return fatCnt; } //****************************************** long long pow_m(long long a,long long n)//快速模幂运算 { long long res=1; long long tmp=a%MOD; while(n) { if(n&1){res*=tmp;res%=MOD;} n>>=1; tmp*=tmp; tmp%=MOD; } return res; } long long sum(long long p,long long n)//计算1+p+p^2+````+p^n { if(p==0)return 0; if(n==0)return 1; if(n&1)//奇数 { return ((1+pow_m(p,n/2+1))%MOD*sum(p,n/2)%MOD)%MOD; } else return ((1+pow_m(p,n/2+1))%MOD*sum(p,n/2-1)+pow_m(p,n/2)%MOD)%MOD; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int A,B; getPrime(); while(scanf("%d%d",&A,&B)!=EOF) { getFactors(A); long long ans=1; for(int i=0;i<fatCnt;i++) { ans*=(sum(factor[i][0],B*factor[i][1])%MOD); ans%=MOD; } printf("%I64d\n",ans); } return 0; }
人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想