• 牛客20347 SDOI2011计算器(bsgs


    https://ac.nowcoder.com/acm/problem/20347

    这篇是为了补bsgs(北上广深算法)。

    题意:

    1、给定y,z,p,计算Y^Z Mod P 的值; 
    2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;
    3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。
     
    思路:
    1.当然是裸的快速幂取模啦。
    2.原式<=>yx+pk=z有解,exgcd记录d=gcd(y,p),看是否d|z即可。
    3.要求满足形如a^x ≡ b (mod p)的最小非负整数x。
    由周期性只需在[0,p)讨论即可,证明的话,抽屉原理显然,或者由费马小定理(  当p为质数且(a,p)=1时 a^(p-1)=1 (mod p)  )能推出a^k=a^(k mod (p-1)) (mod p)。
    把x分块,每块长度是m,其中m=ceil(sqrt(p)),则a^(i*m-j) = b (mod p),移项得a^(i*m) = b*a^j (mod p)
    枚举j(范围0-m),将b*a^j存入哈希表。
    枚举i(范围1-m),从哈希表找出第一个满足a^(i*m) = b*a^j (mod p)的i
    此时x = i*m-j就是答案
    时间复杂度O(m+p/m),m取√p时最优。
     
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define int long long
     4 int T,k,a,b,p;
     5 map<int,int>mp;
     6 
     7 int kuai(int a,int b,int mod)
     8 {
     9     if(b==1)return a;
    10     int x=kuai(a,b/2,mod);
    11     if(b%2==0)return x*x%mod;
    12     else return x*x%mod*a%mod;
    13 }
    14 
    15 void exgcd(int a,int b,int &d,int &x,int &y)
    16 {
    17     if(b==0){d=a;x=1;y=0;}
    18     else{exgcd(b,a%b,d,y,x);y-=x*(a/b);}
    19 }
    20 
    21 int bsgs(int a,int b,int p){
    22     a%=p;b%=p;
    23     if(!a&&!b) return 1;
    24     if(!a||!b) return -1;
    25     mp.clear();
    26     int m = ceil(sqrt(1.0*p)),tmp=1;
    27     mp[tmp*b%p]=0;
    28     for(int j=1;j<=m;j++){
    29         tmp = tmp*a%p;
    30         if(!mp[tmp*b%p]) mp[tmp*b%p] = j;
    31     }
    32     int t = 1,ans;
    33     for(int i=1;i<=m;i++){
    34         t=t*tmp%p;
    35         if(mp[t]){
    36             ans = i*m-mp[t];
    37             return (ans%p+p)%p;
    38         }
    39     }
    40     return -1;
    41 }
    42 
    43 signed main(){
    44     
    45    scanf("%lld%lld",&T,&k);
    46     while(T--)
    47     {
    48         scanf("%lld%lld%lld",&a,&b,&p);
    49         if(k==1)printf("%lld
    ",kuai(a,b,p)%p);
    50         else if(k==2)
    51         {
    52             int x=0,y=0,d;
    53             exgcd(a,p,d,x,y);
    54             if(b%d)
    55             {
    56                 puts("Orz, I cannot find x!");
    57                 continue;
    58             }
    59             x=x*b/d;
    60             x=(x%p+p)%p;
    61             printf("%lld
    ",x);
    62         }
    63         else{
    64             int ans=bsgs(a,b,p);
    65             if(ans==-1)puts("Orz, I cannot find x!");
    66             else printf("%lld
    ",ans);
    67         }
    68     }
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    Github 代码在线在vscode中打开
    TP5如何查询字段为空
    浏览器总是报 'https://static.hae123.cn/gc/gc3.js 错误
    Sublime 复制到word 如何保留样式?
    pdf 在浏览器中是下载,而不是打开如何实现?
    Shell脚本中的set指令,比如set -x 和 set -e【转】
    Python面向对象进阶【转】
    Redis为什么变慢了?常见延迟问题定位与分析【转】
    史上最全的 Linux Shell 文本处理工具集锦【转】
    Linux运维常用命令总结【转】
  • 原文地址:https://www.cnblogs.com/wzgg/p/11371034.html
Copyright © 2020-2023  润新知