POJ1845Sumdiv题解--约数之和

题目链接

https://cn.vjudge.net/problem/POJ-1845

分析

\(POJ\)里的数学题总是这么妙啊

首先有一个结论就是\(A=\prod{ \ {p_i}^{c_i} \ }\),那么\(A\)所有约数之和为\((1+p_1+p_1^2+..+p_1^{c_1}) * (1+p_2+p_2^2+...+p_2^{c_2}) ... (1+p_n +p_n^2 +... + p_n^{c_n})\)

这个好像数学归纳法可证,但是感性理解一下也不难

于是这道题就是求\(A^B = \prod { \ {p_i}^{B \times c_i} \ }\)的所有约数之和,按上面的式子化为等比数列后就是求\(\prod {(p_i^{b \times c_i+1}-1)} / {(p_i-1) }\)

直接质因数分解后快速幂逆元即可

注意

虽然模数\(9901\)是个质数,但是这个数太小了,如果\(p_i-1\)\(9901\)的倍数的话显然逆元都不存在了,但此时\(p_i \equiv 1 \mod 9901\),于是上述等比数列求和其实就是\((1+1+1^2+1^3+...+1^{B \times c_i}) \equiv B \times c_i+1\)

真坑啊

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cctype>
#define ll long long 
#define ri register int 
using std::min;
using std::max;
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c=='-';
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;return ;
}
const int maxn= 100005;
const int inf= 0x7fffffff;
const ll p=9901;
int a,b;
int fac[maxn],cnt=0,ci[maxn];
inline void divide(int n){
    for(ri i=2;i<=n;i++){
        if(n%i)continue;
        fac[++cnt]=i;
        ci[cnt]=1;
        n=n/i;
        while(!(n%i)){n=n/i,ci[cnt]++;}
    }
    if(n>1){fac[++cnt]=n,ci[cnt]=1;}
    return ;
}

int ksm(int x,ll c){
    int ans=1;
    while(c){
        if(c&1)ans=1ll*ans*x%p;
        x=1ll*x*x%p;
        c=c>>1;
    }
    return ans;
}
int main(){
  int x;
    ll ans=1,y;
    read(a),read(b);
    divide(a);
    for(ri i=1;i<=cnt;i++){
        x=fac[i];
        y=ci[i]*b;
        if((x-1)%p==0){
            ans=(y+1)%p*ans%p;
        }
        else{
            ans=(ksm(x,y+1)%p-1+p)*ksm(x-1,p-2)%p*ans%p; 
            //注意+p,不然可能是负的 
        }
    }
    printf("%lld\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/Rye-Catcher/p/9648292.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值