[bzoj 1951] [Sdoi2010]古代猪文

本文探讨了在大数运算中使用中国剩余定理(CRT)解决特定数学问题的方法。通过将复杂指数运算分解为针对多个质数因子的独立运算,再利用CRT整合结果,有效地解决了模大数的指数运算问题。

传送门

Description

给定两个数\(N\)\(G\) (\(N,G\leq 10^9\)),求
\[ ans=G^{\sum_{d|N} \tbinom{N}{d}} (mod \ 999911659) \]

Solution

  1. 运用欧拉定理,所以指数只需要$\sum_{d|N}\tbinom{N}{d} mod   999911658 $
  2. 运用\(Lucas\)定理,\(\tbinom{m}{n} \equiv \tbinom{m/p}{n/p} \tbinom{m\%p}{n\%p}\ \mod p\),其中\(p\)是个质数
  3. 但是\(999911658\)并不是个质数,不能用\(Lucas\)定理。这时我们把它分解:\(999911658=2*3*4679*35617\),对这\(4\)个质因子分别求解出它的答案\(X[i]\),原问题转化成一个解线性方程组的问题,因为\(999911658\)比较小,所以直接用中国剩余定理即可解决。

\[ G的指数=\sum X[i] \ \left ( \frac{M}{p_i}\right )^{-1}_{p_i}\ \frac{M}{m_i} \]


Code 

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define mod 999911659
#define Mod 999911658
#define MN 35620
ll N,G,mo,X[4],fac[MN],inv[MN];
const int p[4]={2,3,4679,35617};
ll C(ll n,ll m)
{
    if(n<m) return 0ll;
    if(n<mo&&m<mo) return fac[n]*inv[m]%mo*inv[n-m]%mo;
    return C(n%mo,m%mo)*C(n/mo,m/mo)%mo;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(!b) return (void)(d=a,x=1,y=0);
    exgcd(b,a%b,d,y,x);y-=x*(a/b);
}
ll CRT()
{
    ll ret=0,d,x,y;register int i;
    for(i=0;i<4;++i)
    {
        exgcd(Mod/p[i],p[i],d,x,y);
        ll INV=(x%Mod+Mod)%Mod;
        (ret+=INV*X[i]%Mod*(Mod/p[i])%Mod)%=Mod;
    }
    return ret;
}
ll fpow(ll x,ll m)
{
    ll ret=1;
    for(;m;x=x*x%mod,m>>=1) if(m&1) ret=ret*x%mod;
    return ret;
}
int main()
{
    N=read();G=read();
    register int i,T;
    for(T=0;T<4;++T)
    {
        mo=p[T];fac[0]=1;
        for(i=1;i<mo;++i) fac[i]=fac[i-1]*i%mo;
        inv[mo-1]=mo-1;
        for(i=mo-2;~i;--i) inv[i]=inv[i+1]*(i+1)%mo;
        for(i=1;i*i<=N;++i)
        {
            if(N%i) continue;
            (X[T]+=C(N,i))%=mo;
            if(N/i-i) (X[T]+=C(N,N/i))%=mo;
        }
    }
    printf("%lld\n",fpow(G,CRT()));
    return 0;
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

转载于:https://www.cnblogs.com/PaperCloud/p/10245403.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值