POJ1845 Sumdiv 数学?逆元?

当初写过一篇分治的

题意:求A^B的所有因子之和,并对其取模 9901再输出

对于数A=p1^c1+p2^c2+...+pn*cn,它的所有约数之和为(1+p1+p1^2+p1^3+...+p1^(c1*B))*(1+p2+p2^2+p2^3+...+p2^(c2*B))*...*(1+pn+pn^2+pn^3+...+pn^(cn*B))

注意到约数之和的每一项都是等比数列,可以用通项搞他,先用快速幂计算分子,再求出分母的乘法逆元。

特别地,当分母pi-1为9901的倍数时,乘法逆元不存在,但是1,pi,pi^2...pi^(ci*B) ≡ 1 (mod 9901) 

所以此时贡献即为B*ci+1 mod 9901

#include<cstdio>
#include<iostream>
#define ll long long
#define R register int
using namespace std;
const int M=9901;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int a,b,cnt;
int p[20],c[20];
ll ans=1;
inline void div(int n) {
    for(R i=2;i*i<=n;++i) if(n%i==0) {
        p[++cnt]=i; while(n%i==0) n/=i,++c[cnt];
    } if(n>1) p[++cnt]=n,c[cnt]=1;
}
inline int qpow(int a,ll p) { R ret=1; a%=M;
    for(;p;p>>=1,(a*=a)%=M) if(p&1) ret=(ll)ret*a%M; return ret;
}
signed main() {
    a=g(),b=g(); div(a);
    for(R i=1;i<=cnt;++i) {
        if((p[i]-1)%M==0) {
            ans=((ll)b*c[i]+1)%M*ans%M;
            continue;
        }
        R x=(qpow(p[i],(ll)b*c[i]+1)-1+M)%M;
        R y=qpow(p[i]-1,M-2); 
        ans=(ll)ans*x%M*y%M;
    } printf("%lld\n",ans);
}

2019.05.11

转载于:https://www.cnblogs.com/Jackpei/p/10847493.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值