poj 1845 Sumdiv 素数筛+快速幂求逆元+二分乘法

来源:互联网 发布:java类的成员变量 编辑:程序博客网 时间:2024/06/05 21:16

点这里

站在巨人肩膀上做题。。。。

这里有一篇写的很清楚的文章(侵删)

点击打开链接

下附部分截图

因子和的公式

这道题如果知道如上的公式 就比较容易解了

所以结果为


ans%=mod

注意乘法的时候需要用二分乘法  直接乘会爆long long

然后快速幂 求逆元

A/B mod C = (A mod (B*C))/ B

#include <iostream>#include <string.h>#include <stdio.h>#include <math.h>#define mod 9901using namespace std;typedef long long ll;int prime[1000005];int vis[1000005],cnt;void init(){    cnt = 0;    memset(vis,0,sizeof(vis));    for(int i=2; i<1000005; i++)    {        if(!vis[i])        {            prime[cnt++]=i;            for(int j=i+i; j<1000005; j+=i)                vis[j]=1;        }    }}ll cf(ll b,ll m,ll tt)//直接乘 会爆精度 所以用加法{    ll ans=0;    while(m)    {        if(m&1)            ans=(ans+b)%tt;        m>>=1;        b=(b+b)%tt;    }    return ans;}ll quickmod(ll n,ll m,ll tt){    ll ans=1;    while(m)    {        if(m&1)            ans=cf(ans,n,tt)%tt;        m>>=1;        n=cf(n,n,tt)%tt;    }    return ans;}int main(){    ll a,b;    init();    while (~scanf("%lld %lld",&a,&b))    {        ll ans=1;        ll x=a;        for(int i=0; prime[i]*prime[i]<=a; i++)        {            if(a%prime[i]==0)            {                ll tmp=0;                while(x%prime[i]==0)                {                    tmp++;                    x/=prime[i];                }                ll mb=mod*(prime[i]-1);                ans=ans*(quickmod(prime[i],b*tmp+1,mb)-1)/(prime[i]-1);                ans%=mod;            }        }        if(x>1)        {            ll mb=mod*(x-1);            ans=ans*(quickmod(x,b+1,mb)-1)/(x-1);            ans%=mod;        }        cout<<ans<<endl;    }    return 0;}