AcWing 224. 计算器 (BSGS算法)打卡

题目:https://www.acwing.com/problem/content/226/

题意:有一个计算器能完成三种功能

1、给定Y,Z,P,计算YZModPYZModP 的值;

2、给定Y,Z,P,计算满足xYZ(modP)xY≡Z(modP)的最小非负整数;

3、给定Y,Z,P,计算满足YxZ(modP)Yx≡Z(modP)的最小非负整数。

思路:第一种很明显就是个快速幂取模,第二种,因为p是个质数,所以我们可以用快速幂取逆元来计算,第三种就是BSGS的板子

#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
#define ll long long
//快速幂求a^b
LL power(LL a,LL b,LL n)
{
    LL s=1;
    while(b)
    {
        if(b&1)
            s=(s*a)%n;
        a=(a*a)%n;
        b=b>>1;
    }
    return s;
}
ll work2(ll y,ll z,ll p)//xy=z mod p
{
    if(y%p==0&&z!=0) return -1;
    return z*power(y,p-2,p)%p;
}
ll bsgs(ll a,ll b,ll p){
    map<ll,ll> hash;
    hash.clear();
    b%=p;
    ll t=(ll)sqrt(p)+1;
    for(int j=0;j<t;j++){
        ll val = (ll)b*power(a,j,p)%p;
        hash[val]=j;
    }
    a=power(a,t,p);
    if(a==0) return b==0?1:-1;
    for(int i=0;i<=t;i++){
        ll val = power(a,i,p);
        ll j=hash.find(val)==hash.end()?-1:hash[val];
        if(j>=0&&i*t-j>=0) return i*t-j; 
    } 
    return -1;
}
int main()
{
    LL a,b,t,n;
    ll op;
    scanf("%lld%lld",&t,&op);
    for(int i=0;i<t;i++){ 
        scanf("%lld%lld%lld",&a,&b,&n);
        if(op==1){
            printf("%lld\n",power(a,b,n));
        }
        else if(op==2){
            ll w=work2(a,b,n);
            if(w==-1) printf("Orz, I cannot find x!\n");
            else printf("%lld\n",w);
        }
        else if(op==3){
            ll w=bsgs(a,b,n);
            if(w==-1)    printf("Orz, I cannot find x!\n");
            else printf("%lld\n",w);
        } 
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Lis-/p/11290502.html
今日推荐