poj 1845 Sumdiv
2016-08-19 15:34
429 查看
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 19177 | Accepted: 4819 |
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).
Source
题意:
:求 A^B的所有约数之和对9901取模后的结果.
以下知识要掌握:
1. 计算约数之和公式
设一个数为A,分解质因数得
A=a1^b1 * a2^b2 * a3^b3 an^bn [a1 a2 a3 .表示不同的质因数 b1 b2 b3 表示每个质因数的次方数(即相同质因数的个数)]
则有:
A的约数的个数=(1+b1)(1+b2)(1+b3).(1+bn)
A的约数的总和=(1+a1+a1^2+a1^3+a1^4+.a1^b1)*(1+a2+a2^2+a2^3+a2^4+.a2^b2).(1+an+an^2+an^3+an^4+.an^bn)
举例说明白:
180=2^2*3^2*5(这个式子能够由唯一分解定理得出,就是学习知识点2)
个数=(1+2)(1+2)(1+1)=18
总和=(1+2+4)(1+3+9)(1+5)=546(这一题最终所要求取的模,如何求取就要学习知识点3了)
2. 唯一分解定理
算术基本定理,又称为正整数的唯一分解定理,即:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。例如:
算术基本定理的内容由两部分构成:
分解的存在性;
分解的唯一性,即若不考虑排列的顺序,正整数分解为素数乘积的方式是唯一的。
那如何实现唯一分解定理呢?在代码中你会得到答案的。
3. 等比数列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)
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
1+p+p^2+p^3+........+p^n=(1+p+p^2+....+p^(n/2-1))*(1+p^(n/2+1))+p^(n/2);
4. 同余模公式
(a+b)%m=(a%m+b%m)%m
(a*b)%m=(a%m*b%m)%m
5. 蒙哥马利模乘
对幂次方取模的优化
蒙哥马利模乘的优点在于减少了取模的次数(在大数的条件下)以及简化了除法的复杂度(在2的k次幂的进制下除法仅需要进行左移操作)。模幂运算是RSA
的核心算法,最直接地决定了RSA 算法的性能。针对快速模幂运算这一课题,西方现代数学家提出了大量的解决方案,通常都是先将幂模运算转化为乘模运算。
例如求D=C^15%N
由于:a*b % n = (a % n)*(b % n) % n
所以令:
C1 =C*C % N =C^2 % N
C2 =C1*C1 % N =C^3 % N
C3 =C2*C2 % N =C^6 % N
C4 =C3*C3 % N =C^7 % N
C5 =C4*C4 % N =C^14 % N
C6 =C5*C % N =C^15 % N
即:对于E=15的幂模运算可分解为6 个乘模运算
经过以上知识的补充就可以知道怎样做此题了,希望对读者能够有更好的帮助。
代码如下:
Memory: 388K Time: 0MS Language: G++ Result: Accepted Source Code #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int MAX = 9901; int n, m; int size; struct node { int prime; //存数 int num; //存幂 }Pri[10002]; /*唯一分解定理的实现*/ void PrimeNum() { int i; size = 0; for ( i = 2;i*i <= n; i++ ) { if ( n%i == 0 ) { Pri[size].prime = i; Pri[size].num = 0; while (n%i == 0) { n = n/i; Pri[size].num++; } size++; } if ( i != 2 ) { i++; } } if ( n != 1 ) { Pri[size].prime = n; Pri[size].num = 1; size++; } } /*蒙哥马利模乘法*/ int power( long long pe, long long pi ) { int exponen = 1; while ( pi >= 1 ) { if ( pi%2 == 1 ) { exponen = (exponen*(pe%MAX))%MAX; } pi = pi/2; pe = pe*pe%MAX; } return exponen; } /*等比公式的二分法*/ int Geomet( long long pe, long long pi ) { if ( pi == 0 ) return 1; if ( pi%2 == 0 ) { return( (Geomet(pe, pi/2-1)%MAX)* ((power(pe, pi/2+1)+1)%MAX) +power(pe, pi/2) )%MAX; } else { return (Geomet(pe, pi/2)%MAX)*((power(pe, pi/2+1)+1)%MAX)%MAX; } } int main() { int i; scanf ( "%d %d", &n, &m ); PrimeNum(); int sum = 1; /*计算约数之和公式*/ for ( i = 0;i < size; i++ ) { /* 同余模公式*/ sum = (sum* ( Geomet (Pri[i].prime, Pri[i].num*m) %MAX ) %MAX); } printf ( "%d\n", sum ); }
代码菜鸟,如有错误,请多包涵!!!
如果有帮助记得支持我一下,谢谢!!!
相关文章推荐
- poj_1845 Sumdiv(素因子分解+快速幂+约数和+二分求等比数列和)
- POJ 1845 Sumdiv
- [POJ1845]Sumdiv
- poj-1845 Sumdiv && nyoj - 928 小M的因子和
- POJ 1845 Sumdiv
- POJ 1845 Sumdiv
- POJ1845 Sumdiv
- POJ 1845 Sumdiv (因子和)
- POJ 1845 Sumdiv <数论(逆元 / 二分递归)>
- POJ 1845 Sumdiv(求阶乘的因子和)
- POJ 1845 Sumdiv(质因数分解+快速幂+二分法求等比数列的和)
- POJ-1845 Sumdiv
- poj 1845 Sumdiv
- POJ 1845-Sumdiv【经典数学题目---求因子和】
- POJ1845------Sumdiv
- POJ 1845 - Sumdiv
- poj 1845 Sumdiv --- 因数分解
- POJ1845 Sumdiv 费马小定理+欧拉函数+素因子分解
- POJ 1845 Sumdiv(数论+快速幂)
- [poj1845] Sumdiv(数论,质因数分解,约数和,快速幂)