BZOJ2242 SDOI2011 计算器 快速幂+逆元+BSGS

Q1:快速幂 Q2:移项之后逆元 Q3:BSGS

code:

#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long

ll y,z,p,T,L;
map<ll,ll> table;
map<ll,ll>::iterator it;

ll Quick_Pow(ll x,ll y,ll p){
    x%=p;
    ll t=(y&1?x:1);

    while(y>>=1){
        x*=x,x%=p;
        if(y&1) t*=x,t%=p;
    }
    return t;
}

void exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x=1,y=0;
        return;
    }
    exgcd(b,a%b,x,y);

    ll t=x;
    x=y,y=t-a/b*y;
}

ll Calc_inv(ll a,ll p){
    ll x,y;
    exgcd(a,p,x,y);
    return (x+p)%p;
}

void Solve_Equation(ll x,ll y,ll p){
    if(!(x%p)) cout << "Orz, I cannot find x!" << endl;
    else cout << (Calc_inv(x,p)*y)%p << endl;
}

void BSGS(ll a,ll b,ll p){
    a%=p,b%=p,table.clear();

    if(!a){
        if(!b) cout << 1 << endl;
        else cout << "Orz, I cannot find x!" << endl;
        return;
    }

    ll m=ceil(sqrt((double)p)),t=1,tmp=1,x,ans=-1;

    for(int i=0;i<m;i++,t=t*a%p) table[t]=i;

    for(int i=0;i<=m;i  ++){
        x=Calc_inv(tmp,p),it=table.find(x*b%p);
        if(it!=table.end()){
            ans=i*m+it->second;
            break;
        }
        tmp=tmp*t%p;
    }

    if(ans==-1) cout << "Orz, I cannot find x!" << endl;
    else cout << ans << endl;
}

int main(){
    cin >> T >> L;
    while(T--){
        cin >> y >> z >> p;
        if(L==1) cout << Quick_Pow(y,z,p) << endl;
        if(L==2) Solve_Equation(y,z,p);
        if(L==3) BSGS(y,z,p);
    }

    return 0;
}


你可能感兴趣的:(BZOJ2242 SDOI2011 计算器 快速幂+逆元+BSGS)