古代猪文[SDOI2010]

古代猪文[SDOI2010]

题目大意:求\(g^{ \sum_{k|n} C_n^k}mod\ 999911659\)

前置知识

  • 欧拉定理推论:

    内容:若正整数\(a,p\)互质,则对于任意正整数\(b\),有\(a^b \equiv a^{b\ mod\ \phi(p)} mod\ p\)

    证明:

    \[设b=q\phi(p)+r,0 \le r\lt \phi(p),即r=b\ mod\ \phi(p) \\ a^b \equiv a^{q\phi(p)+r}\equiv(a^{\phi(p)})^q \times a^r \\ 由欧拉定理知:a^{\phi(p)} \equiv 1\ mod \ p\ \Rightarrow\ (a^{\phi(p)})^q \equiv 1^q \equiv 1\ mod \ p \\ 故a^b \equiv (a^{\phi(p)})^q \times a^r \equiv a^r \equiv a^{b\ mod\ \phi(p)}mod\ p \]

  • \(Lucas\)定理

    内容:快速求组合数模质数,公式:\(C_n^m\ mod\ p=C_{\frac{n}{p}}^{\frac{m}{p}} \times C_{n\ mod\ p}^{m \ mod\ p}\)

    int Lucas(int n,int m,int p)
    {
    	if(n<p&&m<p) return C(n,m);
    	return Lucas(n/p,m/p)*C(n%p,m%p)%p;
    }
    
  • 中国剩余定理(CRT)

    内容:已知\(n\)个非负整数\(a_1,a_2,...,a_n\)\(n\)个互质的整数\(m_1,m_2,...,m_n\),且满足\(a_1\lt m_1,...,a_n \lt m_n\),求一个整数\(x\),满足:

    \[\begin{cases} x \equiv a_1\ mod\ m_1 \\ x \equiv a_2\ mod\ m_2\\ \ \ \ \ \ \ \ \ \ ...\\ x \equiv a_n\ mod\ m_n \end{cases} \tag{1} \]

    求解方法:令\(M=\prod_{i = 1}^{n}m_i\)\(M_i=\frac{M}{m_i}\),且\(y_i\)\(M_i\)\(m_i\)意义下的逆元(\(M_iy_i \equiv 1\ mod\ m_i\))

    ​ 则\(x=(\sum_{i=1}^na_iy_iM_i)\ mod\ M=(\sum_{i=1}^na_iM_i^{\phi(m_i)})\ mod\ M\)

本题解法

由于\(999911659\)是质数,故\(\phi(999911659)=999911658\)

\(g^{ \sum_{k|n} C_n^k}mod\ 999911659 \Rightarrow\ g^{ \sum_{k|n} C_n^k} \equiv g^{ \sum_{k|n} C_n^k\ mod\ \phi(999911659)} \equiv g^{ \sum_{k|n} C_n^k\ mod\ 999911658}\ mod\ 999911659\)

于是只要计算\(\sum_{k|n} C_n^k\ mod\ 999911658\)即可,但由于\(999911658\)不是质数,不好用\(Lucas\)定理处理,怎么办呢?

注意到\(999911658=2\times 3\times 4679\times 35617\),枚举\(k\),对于固定的\(k\),设\(m_1,m_2,m_3,m_4\) 分别为\(\sum_{k|n} C_n^k\)\(2,3,4679,35617\)之后的值,其中\(m_1,m_2,m_3,m_4\)可以用\(Lucas\)定理求。于是设 \(x=\sum_{k|n} C_n^k\ mod\ 999911658\),则

\[\begin{cases} x \equiv m_1\ mod\ 2 \\ x \equiv m_2\ mod\ 3\\ x \equiv m_3\ mod\ 4679\\ x \equiv m_4\ mod\ 35617 \end{cases} \tag{1} \]

\(CRT\)\(x\)即可

,

#include <bits/stdc++.h>
#define lll __in128
#define ll long long 
#define pb push_back
#define endl '\n'
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define fi first
#define se second
#define ls tr[rt].l
#define rs tr[rt].r
using namespace std;
const int N = 1e5 + 6;
const ll mod= 999911658;
ll frac[N],b[4]={2,3,4679,35617},c[5],ans;
ll qmi(ll x,ll y,ll p)
{
    ll res=1;
    while(y)
    {
        if(y&1) res=res*x%p;
        x=x*x%p;
        y>>=1;
    }
    return res;
}

ll C(ll n,ll m,ll p)
{
     if(n<m) return 0;
     return frac[n]*qmi(frac[m],p-2,p)%p*qmi(frac[n-m],p-2,p)%p;
}
ll Lucas(ll n,ll m,ll p)
{
	if(n<p&&m<p) return C(n,m,p);
	return Lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}
void CRT()
{
    for(int i=0;i<4;i++)
    ans=(ans+c[i]*(mod/b[i])%mod*qmi(mod/b[i],b[i]-2,b[i]))%mod;
}
int main()
{
    ll n,g;
    cin>>n>>g;
    frac[0]=1;
    if(g%(mod+1)==0) 
    {
        puts("0");
        return 0;
    }
    for(int j=0;j<4;j++)
    {
        for(int i=1;i<=b[j];i++)
        frac[i]=frac[i-1]*i%b[j];
        for(ll i=1;i*i<=n;i++)
        if(n%i==0)
        {
           c[j]=(c[j]+Lucas(n,i,b[j]))%b[j];
           if(i*i!=n) c[j]=(c[j]+Lucas(n,n/i,b[j]))%b[j];

        }
    }
    CRT();
    cout<<qmi(g,ans,mod+1)<<endl;
    return 0;
}
posted @ 2022-02-09 23:59  Arashimu  阅读(43)  评论(0)    收藏  举报