POJ1845 Sumdiv

逆元

题目传送门

题目大意:给你两个正整数A、B,求 AB 的所有因子之和 mod 9901

把A分解成质因数形式

AB=pa1B1pa2B2panBn

一个数的质因子之和
ϕ(n)=pa1+11p11×pa2+12p21××pan+1npn1

于是
AB=pa1B+11p11×pa2B+12p21××panB+1npn1

然后因为每个 p a的指数都很大 废话,所以我们需要用到快速幂,而快速幂在模的时候需要用到一般求逆元的方法。
ans=abmod m=a mod (mb)/b

然后就差不多了

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 10000
#define WJD 9901//不要在意名字
using namespace std;
typedef long long LL;
LL a,b;
LL prime[MAXN+5],p,t,num[MAXN+5][2];
bool f[MAXN+5];
void Make(){//筛素数
    memset(f,true,sizeof(f));
    for (LL i=2;i<=MAXN;i++){
        if (f[i]) prime[++p]=i;
        for (LL j=1;j<=p&&prime[j]*i<=MAXN;j++){
            f[i*prime[j]]=false;
            if (i%prime[j]==0) break;
        }
    }
}
void fenjie(LL x){//质因数分解
    LL node=1; memset(num,0,sizeof(num));
    while (x>1&&node<=p){
        if (x%prime[node]==0) num[++t][0]=prime[node];
        while (x%prime[node]==0){
            x/=prime[node]; num[t][1]++;
        }
        node++;
    }
    if (x>1) {
        num[++t][0]=x; num[t][1]=1;
    }
}
LL mul(LL a,LL b,LL m){//快速乘
    LL ret=0; a%=m;
    while (b){
        if (b&1)
            ret=(ret+a)%m;
        a=(a+a)%m;
        b/=2;
    }
    return ret;
}
LL qsm(LL a,LL b,LL m){//快速幂
    LL ret=1; a%=m;
    while (b){
        if (b&1)
            ret=mul(ret,a,m);
        a=mul(a,a,m);
        b/=2;
    }
    return ret;
}
int main(){
    Make(); 
    while (scanf("%lld%lld",&a,&b)==2){
        fenjie(a); LL ans=1;
        for (LL i=1;i<=t;i++){
            LL M=(LL)(num[i][0]-1)*WJD;
            ans*=(qsm(num[i][0],num[i][1]*b+1,M)+M-1)/(num[i][0]-1)%WJD;//求逆元把除换成乘
            ans=(ans+WJD)%WJD;
        }
        printf("%lld\n",ans);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值