BZOJ 2242: [SDOI2011]计算器 BSGS

这里讲一下普通的 BSGS 如何实现:   

我们要求解形如 $y^x \equiv z(\mod p)$ 的 $x$ 的整数解(其中 $gcd(y,p)=1$)   

我们将 $x$ 写成 $am-b$ 的形式,原式就变为 $y^{am} \equiv z \times y^b (\mod p)$    

然后 $b<m$,可以枚举右面所有的取值,然后再枚举左面,整个时间复杂度是 $max(m,\frac{p}{m})$    

然后 $m$ 取到 $\sqrt p$ 时时间复杂度是最优的.   

这道题中要特判一下无解的情况. 

code: 

#include <cstdio> 
#include <map> 
#include <cstring> 
#include <cmath>
#include <algorithm>  
#define ll long long      
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int mod; 
map<int,int>bu;    
int qpow(int x,int y) 
{ 
    int tmp=1;
    for(;y;y>>=1,x=(ll)x*x%mod) 
        if(y&1) tmp=(ll)tmp*x%mod;
    return tmp; 
}    
int exgcd(int a,int b,int &x,int &y) 
{
    if(!b) { x=1,y=0; return a;}      
    int gcd=exgcd(b,a%b,x,y),tmp=x;     
    x=y,y=tmp-a/b*y;       
    return gcd;    
}
void work_1()
{
    int i,j,x,y;   
    scanf("%d%d%d",&x,&y,&mod);    
    printf("%d\n",qpow(x,y));    
}
void work_2() 
{ 
    int i,j,x,y,z,a,b,c; 
    scanf("%d%d%d",&a,&c,&mod),b=mod;     
    int gcd=exgcd(a,b,x,y);                    
    if(c%gcd||(a==0&&c!=0)) printf("Orz, I cannot find x!\n");   
    else 
    {
        int t=abs(b/gcd);     
        x=(ll)((ll)x*(c/gcd)%t+t)%t;   
        printf("%d\n",x);   
    }
}
void work_3()
{         
    int i,j,y,z,m;     
    scanf("%d%d%d",&y,&z,&mod),m=sqrt(mod)+1;    
    if(y%mod==0&&z) 
    {
        printf("Orz, I cannot find x!\n");
        return;   
    }
    if(z%mod==1) { printf("0\n");   return ; }   
    bu.clear();     
    int now=z%mod;    
    bu[now]=0;        
    for(i=1;i<m;++i) now=(ll)now*y%mod,bu[now]=i;             
    int f=qpow(y,m);    
    now=1;            
    for(i=1;i<=m+1;++i) 
    {       
        now=(ll)now*f%mod;         
        if(bu.count(now))   
        {
            printf("%d\n",i*m-bu[now]);     
            return;   
        }            
    }
    printf("Orz, I cannot find x!\n");  
}
int main() 
{ 
    // setIO("input");  
    int i,j,T,x;     
    scanf("%d%d",&T,&x);   
    while(T--) 
    {
        if(x==1) work_1();     
        if(x==2) work_2();   
        if(x==3) work_3();  
    }
    return 0;  
}

  

posted @ 2020-02-04 09:47  EM-LGH  阅读(161)  评论(0编辑  收藏  举报