POJ 1845 Sumdiv (数学,乘法逆元)

题意:

  给出数字A和B,要求AB的所有因子(包括AB和1)之和 mod 9901 的结果。

思路:

  即使知道公式也得推算一阵子。

  很容易知道,先把分解得到,那么得到,那么的所有因子之和的表达式如下:

  

  我们要做的就是计算出sum%9901的结果。

  有两种方法:

  (1)直接用快速幂计算对上面sum的第一步推算求结果,在计算过程中顺便取模。

  (2)可以根据以下这条公式对上面sum的第二步推算求结果:

     

    也是需要用到快速幂,过程也稍微复杂了些。注意 mb 可能会超过int。

  以下是第二种方法的代码:

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <map>
 7 #include <algorithm>
 8 #include <vector>
 9 #include <iostream>
10 #define pii pair<int,int>
11 #define INF 2147483647
12 #define LL unsigned long long
13 using namespace std;
14 const double PI  = acos(-1.0);
15 const int N=10010;
16 const LL mod=9901;
17 bool isPrime[N];
18 LL p[N];       //素数表
19
20 int get_all_prime(int n)    //筛法求所有[0~n)素数,返回素数表大小
21 {
22     memset(isPrime, 1, sizeof(isPrime));
23     int cnt=0;
24     for(int i=2; i<n; i++)
25     {
26         if(!isPrime[i])    continue;
27         p[cnt++]=i;
28         for(int j=i*i; j<n; j+=i)    isPrime[j]=0;
29     }
30     return cnt;
31 }
32
33 LL _mul(LL a,LL b,LL mod)   //a*b要用加法形式运算才不会溢出
34 {
35     a%=mod;
36     LL r=0;     //结果
37     while( b )
38     {
39         if( b&1 )     r=(r+a)%mod;
40         a=(a+a)%mod;
41         b>>=1;
42     }
43     return r;
44 }
45
46 LL pow(LL a,LL b,LL mod)    //快速幂函取模
47 {
48     a%=mod;
49     LL r=1;     //结果
50     while( b )
51     {
52         if( b&1 )     r=_mul(r,a,mod);
53         a=_mul(a,a,mod);
54         b>>=1;
55     }
56     return r;
57 }
58
59 LL cal(LL A,LL B)
60 {
61     LL ans=1;
62     for(int i=0; p[i]*p[i]<=A; i++ )    //先求A的所有质因子
63     {
64         if(A%p[i]==0)
65         {
66             int cnt=0;
67             while(A%p[i]==0)    //全部取光
68             {
69                 cnt++;
70                 A/=p[i];
71             }
72             LL mb=mod*(p[i]-1);
73             ans*=(pow(p[i], cnt*B+1, mb)+mb-1)%mb/(p[i]-1) ;  //要防止出现负数
74             ans%=mod;
75         }
76     }
77
78     if(A > 1)   //别遗漏了A^B也是其因子
79     {
80         LL mb=mod*(A-1);
81         ans*=(pow(A, B+1, mb)+mb-1)%mb/(A-1) ;  //要防止出现负数
82         ans%=mod;
83     }
84
85     return ans;
86 }
87
88 int main()
89 {
90     //freopen("input.txt", "r", stdin);
91     get_all_prime(N);
92     int A, B;
93     while(~scanf("%d%d",&A,&B))
94         printf("%lld\n", cal(A,B) );
95     return 0;
96 }

AC代码

时间: 2024-10-10 17:19:26

POJ 1845 Sumdiv (数学,乘法逆元)的相关文章

POJ 1845 - Sumdiv ( 数论 + 唯一分解定理 + 快速幂取模 )

POJ 1845 - Sumdiv ( 数论 + 唯一分解定理 + 快速幂取模 ) 这是一道数论的好题,需要较好的数学基础 题意: 给定A,B,求A^B的所有因数的和,再MOD 9901 分析: 这里用到了数论当中相当一部分知识 a. 唯一分解定理 任何一个整数都可以分解为若干个素数的幂的乘积的形式 A = ( p1 ^ q1 + p2 ^ q2 + ..... + pn ^ qn ) p为素数 A^B = ( p1 ^ (q1*B) + p2 ^ (q2*B) + ..... + pn ^ (

poj 1845 Sumdiv (算术基本定理求一个数因子和)

求一个数的所有因子和可以用算术基本定理,下面是它的两个重要应用: (1)一个大于1的正整数N,如果它的标准分解式为: N=(P1^a1)*(P2^a2)......(Pn^an) 那么它的正因数个数为(1+a1)(1+a2).....(1+an). (2) 它的全体正因数之和为d(N)=(1+p1+...p1^an)(1+p2+...p2^a2)...(1+pn+...+pn^an) 和求一个数正因数个数的方法类似. 可以先打表出sqrt(n)以内的所有素数(当然也可以不打表),因为n的素因数中

POJ 1845 Sumdiv【同余模运算+递归求等比数列和+快速幂运算】

快速幂运算在第一次训练时候就已经遇到过,这里不赘述 同余模运算也很简单,这里也不说了,无非是(a+b)%m (a*b)%m 把m弄到里面变成(a%m+b%m)%m   (a%m*b%m)%m 今天学的最重要的还是递归二分求等比数列 题目大意是给出A和B,求A^B的约数和 解这个题,首先,对A进行素因子分解得到 (PI(pi^ai))^B 然后我们有约数和公式: 对A=PI(p1^k1) A的所有因子之和为S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^

POJ 1845 Sumdiv (快速分解因式+快速幂取模)

题目地址:POJ 1845 转载自:http://blog.csdn.net/lyy289065406/article/details/6648539 大致题意: 求A^B的所有约数(即因子)之和,并对其取模 9901再输出. 解题思路: 要求有较强 数学思维 的题 应用定理主要有三个: 要求有较强 数学思维 的题 应用定理主要有三个: (1)   整数的唯一分解定理: 任意正整数都有且只有一种方式写出其素因子的乘积表达式. A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^

【题解】POJ1845 Sumdiv(乘法逆元+约数和)

POJ1845:http://poj.org/problem?id=1845 思路: AB可以表示成多个质数的幂相乘的形式:AB=(a1n1)*(a2n2)* ...*(amnm) 根据算数基本定理可以得约数之和sum=(1+a1+a12+...+a1n1)*(1+a2+a22+...+a2n2)*...*(1+am+am2+...+amnm) mod 9901 对于每个(1+ai+ai2+...+aini) mod 9901=(ai(ni+1)-1)/(ai-1) mod 9901 (等比数列

POJ 1845 Sumdiv(因子分解+快速幂+二分求和)

题意:给你A,B,让求A^B所有的因子和模上9901 思路:A可以拆成素因子的乘积: A = p1^x1 * p2^x2 *...* pn^xn 那么A^B = p1^(B*x1) * p2^(B*x2) *...* pn^(B*xn) 那么A^B所有的素因子和就是 (p1^0 + p1^1 + p1^2 + ... + p1^(B*x1) ) * (p2^0 + p2^1 + ... + p2^(B*x2) ) * ... * (pn^0 + pn^1 + ... + pn^(B*xn)) 可

POJ 1845 Sumdiv (整数拆分+等比快速求和)

当我们拆分完数据以后, A^B的所有约数之和为: sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...*[1+pn+pn^2+...+pn^(an*B)]. 当时面对等比数列的时候,想到了求和公式,因为直接算超时了,但是带膜除法不能直接除,所以又想到了乘法逆元,但是逆元的使用条件是除数和mod互质的时候,题目给我们的膜不够大,然后我就方了,不知道该怎么去处理了,后来看到网上,才学会了等比快速求和的方法. 它的思想是二分法

poj 1845 Sumdiv (同余定理,快速幂取余)

链接:poj 1845 题意:求A^B的所有因子的和对9901取余后的值 如:2^3=8,8的因子有 1,2,4,8,所有和为15,取余后也是15 应用定理主要有三个: (1)整数的唯一分解定理: 任意正整数都有且只有一种方式写出其素因子的乘积表达式. A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)   其中pi均为素数 (2)约数和公式: 对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 有A的所有因子之和为 S = 

POJ 1845 Sumdiv(逆元的应用)

传送门 Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 19009 Accepted: 4773 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 99