Sumdiv
Posted happy_code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sumdiv相关的知识,希望对你有一定的参考价值。
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 20971 | Accepted: 5290 |
Description
Input
Output
Sample Input
2 3
Sample Output
15
Hint
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
1 void Zhi() 2 { 3 int t = a; 4 for (int i=2;i*i<=a;i++) 5 { 6 if (t%i==0) 7 { 8 p[z]=i; 9 p_n[z]=1; 10 t/=i; 11 while (t%i==0) 12 { 13 p_n[z]++; 14 t/=i; 15 } 16 z++; 17 } 18 if (t==1) break; 19 if (i!=2) 20 i++;//2.3.5.7.9... 21 } 22 if (t!=1)//本身就是质数 23 { 24 p[z]=t; 25 p_n[z]=1; 26 z++; 27 } 28 }
对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)
有 A 的所有因子之和为
S = (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)
但是,使用这个公式不能用等比求和公式,因为我们要求余,等比数列求和公式求余就错了
所以用到了二分求等比数列和
用递归二分求等比数列1+pi+pi^2+pi^3+...+pi^n:
(1)若n为奇数,一共有偶数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
= (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
上式中加粗的前半部分恰好就是原式的一半,那么只需要不断递归二分求和就可以了,后半部分为幂次式,在后面就说快速幂。
(2)若n为偶数,一共有奇数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
= (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);
上式加粗的前半部分恰好就是原式的一半,依然递归求解
前提是要用到<同余模公式>
(a+b)%m=(a%m+b%m)%m
(a*b)%m=(a%m*b%m)%m
还有<快速幂>
应该不难,看看代码能懂
1 int Mi(int a, int b)//快速幂 2 { 3 int res = 1; 4 a %= MOD; 5 while (b) 6 { 7 if (b%2==1) 8 res = (res * a)%MOD; 9 a = (a * a)%MOD; 10 b /= 2; 11 } 12 return res; 13 }
好了,递归二分代码
1 int Erfen(int p , int n)//求 1 + p + p^2 + p^3+ ... +p^n 2 { 3 if (n==0) return 1; 4 if (n%2==1) 5 return ((Mi(p,n/2+1)+1) * Erfen(p,n/2))%MOD; 6 else 7 return ((1+Mi(p,n/2+1)) * Erfen(p,n/2-1) + Mi(p,n/2))%MOD; 8 }
上总代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 5 using namespace std; 6 7 #define MOD 9901 8 9 int a,b,z; 10 int p[10000]; //质数 11 int p_n[10000];//质数个数 12 13 void Zhi() 14 { 15 int t = a; 16 for (int i=2;i*i<=a;i++) 17 { 18 if (t%i==0) 19 { 20 p[z]=i; 21 p_n[z]=1; 22 t/=i; 23 while (t%i==0) 24 { 25 p_n[z]++; 26 t/=i; 27 } 28 z++; 29 } 30 if (t==1) break; 31 if (i!=2) 32 i++;//2.3.5.7.9... 33 } 34 if (t!=1)//本身就是质数 35 { 36 p[z]=t; 37 p_n[z]=1; 38 z++; 39 } 40 } 41 42 int Mi(int a, int b)//快速幂 43 { 44 int res = 1; 45 a %= MOD; 46 while (b) 47 { 48 if (b%2==1) 49 res = (res * a)%MOD; 50 a = (a * a)%MOD; 51 b /= 2; 52 } 53 return res; 54 } 55 56 int Erfen(int p , int n)//求 1 + p + p^2 + p^3+ ... +p^n 57 { 58 if (n==0) return 1; 59 if (n%2==1) 60 return ((Mi(p,n/2+1)+1) * Erfen(p,n/2))%MOD; 61 else 62 return ((1+Mi(p,n/2+1)) * Erfen(p,n/2-1) + Mi(p,n/2))%MOD; 63 } 64 65 int main() 66 { 67 while (scanf("%d%d",&a,&b)!=EOF) 68 { 69 z=0;//质数个数 70 Zhi(); 71 72 int ans = 1; 73 for (int i=0;i<z;i++) 74 { 75 ans = (ans * Erfen(p[i],p_n[i]*b))%MOD; 76 } 77 printf("%d\\n",ans); 78 } 79 return 0; 80 }
以上是关于Sumdiv的主要内容,如果未能解决你的问题,请参考以下文章