POJ 1845 Sumdiv(逆元)

题目链接:Sumdiv

题意:给定两个自然数A,B,定义S为A^B所有的自然因子的和,求出S mod 9901的值。

题解:了解下以下知识点
 
1.整数的唯一分解定理

任意正整数都有且只有唯一的方式写出其质因子的乘积表达式

$A={p_1}^{k_1}*{p_2}^{k_2}*{p_3}^{k_3}*...*{p_n}^{k_n}$

2.整数因数个数

$B=(k_1+1)*(k_2+1)*(k_3+1)...*(k_n+1)$

3.整数因数总和

$S=(1+p_1+p_1^2+p_1^3+...+{p_1}^{k_1})*(1+p_2+p_2^2+p_2^3+...+{p_2}^{k_2})*...(1+p_n+p_n^2+p_n^3+...+{p_n}^{k_n})$

明显地:先分解整数A,A的整数因数总和能表示,A^B只不过是pi变成pi^B。

通过等比数列求和公式:$\dfrac{{p_1}^{k_1b+1}-1}{p_1-1}=1+p_1+p_1^2+p_1^3+...+{p_1}^{k_1b}$

费马小定理:

$a^{p-1} ≡1 (mod p)$

两边同除以a

$a^{p-2} ≡inv(a) (mod p)$

$inv(a) = a^{p-2} (mod p)$

快速幂求一下即可:

1 ll fast_mod(ll x,ll y,ll mod){
2     ll res=1;
3     while(y){
4         if(y&1) res=fast_mul(res,x,mod);
5         x=fast_mul(x,x,mod);
6         y>>=1;
7     }
8     return res;
9 }
View Code

直接使用快速幂可能爆long long,结合快速乘防止爆long long:

1 ll fast_mul(ll x,ll y,ll mod){
2     ll res=0;
3     while(y){
4         if(y&1) res=(res+x)%mod;
5         x=(x+x)%mod;
6         y>>=1;
7     }
8     return res;
9 }
View Code

最后一个问题,存在逆元的情况是$ax ≡1(mod p)$

如果a是p的倍数时候左边为0,明显不等于右边。可以使用这个公式

$ans=\dfrac{a}{b}modm=amod(mb)/b$

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N=1e7;
 9 const ll MOD=9901;
10 ll p[N],k[N];
11 ll a,b,c=1;
12 
13 ll fast_mul(ll x,ll y,ll mod){
14     ll res=0;
15     while(y){
16         if(y&1) res=(res+x)%mod;
17         x=(x+x)%mod;
18         y>>=1;
19     }
20     return res;
21 }
22 
23 ll fast_mod(ll x,ll y,ll mod){
24     ll res=1;
25     while(y){
26         if(y&1) res=fast_mul(res,x,mod);
27         x=fast_mul(x,x,mod);
28         y>>=1;
29     }
30     return res;
31 }
32 
33 void solve(){
34     ll res=1;
35     for(ll i=1;i<c;i++){
36         ll M=MOD*(p[i]-1);
37         res=res*(fast_mod(p[i],k[i]*b+1,M)+M-1)/(p[i]-1)%MOD;
38     }
39     printf("%lld\n",(res+MOD)%MOD);
40 }
41 
42 int main(){
43     while(scanf("%lld%lld",&a,&b)!=EOF){
44         c=1;
45         for(ll i=2;i*i<=a;i++){
46             if(a%i==0){
47                 ll cnt=0;
48                 p[c]=i;
49                 while(a%i==0) a/=i,cnt++;
50                 k[c]=cnt;
51                 c++;
52             }
53         }
54         if(a>1) {p[c]=a;k[c]=1;c++;}
55         solve();
56     }
57     return 0;
58 }
View Code

 

 

posted @ 2018-10-11 16:16  pavtlly  阅读(294)  评论(0编辑  收藏  举报