• 《算法竞赛进阶指南》0x36 古代猪文 Lucas定理+费马小定理+欧拉定理推论+中国剩余定理


    题目链接:https://www.acwing.com/problem/content/215/

     通过欧拉定理推论可以知道这个公式的计算可以变成对指数%(mod-1)的计算,涉及到组合数取模的问题,遂考虑卢卡斯定理,由于模数不是质数,考虑分解质因数,发现是一个square free number,可以通过模线性方程组来求解这个最小的指数x,求最小的正整数x是因为,如果指数是k*(mod-1)+x的话,根据费马小定理,q^(k*(mod-1))=1%(mod),对结果没有贡献。

    求解过程用到了Lucas定理,和对不同的模质数进行取模。逆元可以用exgcd或者费马小定理在O(logn)时间内求解。

    代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    const ll mod=999911659;
    ll p[5]={0,2,3,4679,35617},m[5]={0},t[5];
    ll pn[5][35620][2];//0存放对应的阶乘取模,1存放阶乘的逆元 
    ll ksm(ll a,ll b,ll mod){
        ll ans=1;
        a%=mod;
        b%=(mod-1);//费马小定理 
        while(b){
            if(b&1)ans=(ans*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return ans;
    }
    ll C(ll n,ll d,ll i){//lucas定理求组合数取模 ,使用第i个模数 
        if(d<p[i] && n<p[i])return pn[i][n][0]*pn[i][d][1]%p[i]*pn[i][n-d][1]%p[i];
        return C(n%p[i],d%p[i],i)*C(n/p[i],d/p[i],i)%p[i];
    }
    int main(){
        ll n,q;
        cin>>n>>q;
        if(q==mod){
            cout<<"0"<<endl;
            return 0;
        }
        for(int i=1;i<=4;i++)pn[i][0][0]=pn[i][0][1]=pn[i][1][0]=pn[i][1][1]=1;
        for(int i=2;i<=4;i++){
            for(int j=2;j<p[i];j++){
                pn[i][j][0]=pn[i][j-1][0]*j%p[i];//阶乘对应取模
                pn[i][j][1]=ksm(pn[i][j][0],p[i]-2,p[i]); 
            }
        }
        
        for(int i=1;i<=4;i++){
            m[i]=(mod-1)/p[i];
            t[i]=ksm(m[i],p[i]-2,p[i]);
        }
        ll a[5]={0,0,0,0,0};
        for(int d=1;d*d<=n;d++){//分解质因数 
            if(n%d==0){
                for(int i=1;i<=4;i++){
                    a[i]=(a[i]+C(n,d,i))%p[i];
                    if(d*d!=n)a[i]=(a[i]+C(n,n/d,i))%p[i];
                }
            }
        }
        ll ans=0;
        for(int i=1;i<=4;i++){//中国剩余定理 
            ans=(m[i]*a[i]%(mod-1)*t[i]%(mod-1)+ans)%(mod-1);
        }
        ans=(ans+mod-1)%(mod-1);//求得指数 
        cout<<ksm(q,ans,mod)<<endl;
        return 0;
    }
  • 相关阅读:
    Java实现串口通信的小样例
    poi读写Excel
    java的list类
    java集合类
    常用正则表达式
    正则表达式
    Java获取路径中的文件名(正则表达式)
    poi读取word2003(.doc文档)中的表格
    使用poi读取word2007(.docx)中的复杂表格
    使用Maven搭建SpringMVC
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13281001.html
Copyright © 2020-2023  润新知