【Luogu】P2485 Calculator (Quick Power, exgcd and Bsgs Template)

  topic link

  The question description is very straightforward, requiring you to solve the first question with fast power, exgcd to solve the second question, and bsgs to solve the third question.

  Emmmm so now learning bsgs

  The second question makes it annoying to find the smallest integer solution...

  Suppose we want the smallest integer solution to the equation $ax+by=c(mod p)$

  Let $d=gcd(a,b)$

  We find a solution $x_0,y_0$ such that $ax_0+by_0=d(mod p)$

  Then $x_0*frac{c}{d}$ is the smallest integer solution.

  

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num = num * 10 + ch - 0 ' ;
        ch=getchar();
    }
    return num*f;
}

long long Pow(long long a,long long b,long long c){
    long long ret=1;
    while(b){
        if(b&1)    ret=(ret*a)%c;
        a=(a*a)%c;
        b>>=1;
    }
    return ret;
}

long long exgcd(long long a,long long b,long long &x,long long &y){
    if(b==0){
        x=1;y=0;
        return a;
    }
    long long tmp=exgcd(b,a%b,x,y);
    long long ret=x;x=y;y=ret-a/b*y;
    return tmp;
}

int main(){
    int n=read(),m=read();
    while(n--){
        int y=read(),z=read(),p=read();
        if(m==1)    printf("%lld\n",Pow(y,z,p));
        else if(m==2){
            long long x,b;
            long long now=exgcd(y,p,x,b);
            if(z%now){
                printf("Orz, I cannot find x!\n");
                continue;
            }
            x/=now;
            //exgcd(y/now,p/now,x,b);
            x=(x+p/now)%(p/now);
            printf("%lld\n",x*(z/now)%(p/now));
        }
        else{
            if(y%p==0){
                printf("Orz, I cannot find x!\n");
                continue;
            }
            map<long long,int>d;
            long long m=ceil(sqrt(p));
            for(int i=0;i<=m;++i)    d[Pow(y,i,p)*z%p]=i;
            long long t=Pow(y,m,p);
            long long ans=1;    bool flag=0;
            for(int i=1;i<=m;++i){
                ans=ans*t%p;
                if(d.count(ans)){
                    long long ret=i*m%p-d[ans]%p;
                    printf("%lld\n",(ret%p+p)%p);
                    flag=1; break;
                }
            }
            if(flag==0)    printf("Orz, I cannot find x!\n");
        }
    }
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324539551&siteId=291194637