Sumdiv Page17 分治/逆元

Sumdiv Page17 分治/逆元

书上的分治方法就不提了

加深一下这题的数论解法

先将A做唯一分解

对于 p 1 b k 1 1 p 1 1 % 9901 {{p_1^{bk_1}-1}\over p_1-1}\%9901 ,可以求出 p 1 1 p_1-1 在模 9901 9901 意义下的逆元(由于 p 1 p_1 肯定是个质数,所以可以用费马小定理求解逆元)

但是有逆元的前提是 p 1 1 p_1-1 9901 9901 互质,由于 9901 9901 本身是个质数,所以他们两个数不互质的数学表达式为 ( p 1 1 ) % 9901 = 0 ({p_1-1})\%9901=0 。这种情况下的处理为将等比公式还原回去,即计算 ( 1 + p 1 + p 1 2 + . . . p 1 b k 1 ) % m o d (1+p_1+{p_1}^2+...{p_1}^{bk_1})\%mod ,由于 p 1 % 9901 = 1 , p 1 2 % 9901 = p 1 % 9901 × p 1 % 9901 = 1 × 1 = 1 , . . . p 1 b k 1 % 9901 = 1 p_1\%9901=1,{p_1}^2\%9901=p_1\%9901×p_1\%9901=1×1=1,...{p_1}^{bk_1}\%9901=1 ,故其结果为 b k 1 + 1 bk_1+1 1 1 相加

代码

#define ll long long
#define rep(x,a,b) for (int x=a;x<=b;x++)
#define WW(x) printf("%lld\n",x)
const ll mod=9901;
int mm,a,b;
struct node
{
    ll x,num;
}p[maxn];
ll qpow(ll a,ll b,ll mod)
{
    ll res=1;
    while(b)
    {
        if (b&1)res=(res*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return res;
}
void solve(int x)
{
    rep(i,2,int(sqrt(x)))
    {
        if (x%i==0)
        {
            ll num=0;
            while(x%i==0)
            {
                x/=i;num++;
            }
            p[mm].x=i;
            p[mm++].num=num;
        }
    }
    if (x>1)
    {
        p[mm].x=x;
        p[mm++].num=1;
    }
}
int main()
{
    while(~scanf("%d%d",&a,&b))
    {
        mm=0;
        solve(a);
        ll ans=1;
        repp(i,0,mm)
        {
            ll x=p[i].x;
            ll num=p[i].num;
            if ((x-1)%mod==0)
            {
                ans=ans*(1+b*num)%mod;
            }
            else
            {
                ll inv=qpow(x-1,mod-2,mod);
                ll pow=qpow(x,b*num+1,mod)-1;
                ans=ans*pow%mod*inv%mod;
            }
        }
        while(ans<0)ans+=mod;
        WW(ans);
    }
}
发布了115 篇原创文章 · 获赞 7 · 访问量 8101

猜你喜欢

转载自blog.csdn.net/w_udixixi/article/details/104649066