• 【CQOI2018】破解D-H协议


    题目链接

    分析:

      已知$g^a=A$和$g^b=B$,求$g^{ab}mod P$,可以先求$a$,再得$B^a$。

      也即,在$g^aequiv Apmod P$中求$a$。显然$BSGS$。

      $g$是原根,这就意味着$g^tmod P;(0leq t<P)$取遍了$[0,P)$,考虑枚举指数找到$a$。

      如何加速?考虑一种拆分方法使得可以预处理一部分,即设$t=i imes m-j$,移项,得到$g^{i imes m}equiv A imes g^jpmod P$。

      预处理:算出所有$g^{i imes m}$插入到桶里(使用$STL-map$)。使用容器之后要注意常数。

      可以发现,当$m=lceilsqrt{P}\, ceil$时有最优复杂度。

    实现(100分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define IL inline
    #define RG register
    #define _1 first
    #define _2 second
    using namespace std;
    typedef long long LL;
    
        LL g,p,m;
        
    IL LL qpow(LL a,LL b){
        LL ret=1;
        while(b>0){
            if(b&1)
                ret=ret*a%p;
            a=a*a%p;
            b>>=1;
            
        }
        
        return ret;
        
    }
        
        map<LL,LL>s;
    IL void init(){
        m=sqrt(p)+1;
        LL t=1,x=qpow(g,m);
        for(LL i=1;i<=m;i++){
            t=t*x%p;
            s[t]=i*m;
            
        }
        
    }
    
    IL LL calc(LL t){
        for(int i=0;i<m;i++){
            if(s.find(t)!=s.end())
                return s[t]-i;
            t=t*g%p;
            
        }
        return 0;
        
    }
    
    int main(){
        scanf("%lld%lld",&g,&p);
        init();
        
        int T;
        scanf("%d",&T);
        while(T--){
            LL a,b;
            scanf("%lld%lld",&a,&b);
            printf("%lld
    ",qpow(b,calc(a)));
            
        }
    
        return 0;
    
    }
    View Code

    小结:

      高级枚举方法get√

  • 相关阅读:
    win10下 Ubuntu 18.04 LTS 的安装及 rlt8821ce网卡驱动的安装
    网络:tcp/ip
    数据结构分类
    面向对象的solid原则
    mysql数据库的操作
    锁机制
    设计模式在项目中的应用
    aop动态代理底层实现模拟
    变量在内存的分配_复习
    java内部类及类加载顺序
  • 原文地址:https://www.cnblogs.com/Hansue/p/12207736.html
Copyright © 2020-2023  润新知