zoukankan      html  css  js  c++  java
  • 离散对数

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    //返回a*b%n,要求0<=a,b<n 
    ll mul_mod(ll a,ll b,ll n){
        return a*b%n; 
    }
    //返回a^p%n,要求0<=a<n 
    ll pow_mod(ll a,ll p,ll n)
    {   
        ll ans=1;  
        while(p>0){  
            if(p&1) ans=(ans*a)%n;  
            a=(a*a)%n;  
            p>>=1;  
        }  
        return ans;
    }
    //扩展欧几里得算法 
    void gcd(ll a,ll b,ll &d,ll &x,ll &y)
    {
        if(!b){
            d=a;
            x=1,y=0;
        }
        else{
            gcd(b,a%b,d,y,x);
            y-=(a/b)*x;
        }
    } 
    //计算模n下a的逆,如果不存在逆,返回-1 
    ll inv(ll a,ll n)
    {
        ll d,x,y;
        gcd(a,n,d,x,y);
        return d==1?(x+n)%n:-1;
    }
    //求解模方程a^x=b(mod n)n为素数。无解返回-1 
    ll log_mod(ll a,ll b,ll n)
    {
        ll e=1;
        ll m=(ll)sqrt(n+0.5);
        ll v=inv(pow_mod(a,m,n),n);
        map<ll,ll> x;
        x[1]=0;
        for(ll i=1;i<m;i++){
            e=mul_mod(e,a,n);
            if(!x.count(e)) x[e]=i;
        }
        for(ll i=0;i<m;i++){
            if(x.count(b)) return i*m+x[b];
            b=mul_mod(b,v,n);
        }
        return -1;
    } 
    int main()
    {
        ll a,b,n;
        scanf("%lld%lld%lld",&a,&b,&n);
        printf("%lld",log_mod(a,b,n));
    }
  • 相关阅读:
    把数组排成最小的数
    整数中1出现的次数
    连续子数组的最大和
    快速排序
    penCV入门
    OpenCV视频操作
    linux下导入oracle数据表
    js工作备注
    oracle创建默认表空间---重要
    oracle的导入导出
  • 原文地址:https://www.cnblogs.com/freinds/p/6406021.html
Copyright © 2011-2022 走看看