BZOJ2242 || 洛谷P2485 [SDOI2011]计算器【扩展欧几里得+BSGS】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/81781431

Time Limit: 10 Sec
Memory Limit: 512 MB

Description

你被要求设计一个计算器完成以下三项任务:
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)的最小非负整数。

Input

输入包含多组数据。

第一行包含两个正整数T,K分别表示数据组数和询问类型(对于一个测试点内的所有数据,询问类型相同)。
以下行每行包含三个正整数y,z,p,描述一个询问。

Output

对于每个询问,输出一行答案。对于询问类型2和3,如果不存在满足条件的,则输出“Orz, I cannot find x!”,注意逗号与“I”之间有一个空格。


题目分析

裸的快速幂+EXGCD+BSGS

扩展欧几里得—推导及应用

BSGS算法


#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef long long lt;

lt read()
{
    lt f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

int T,opt;
map<int,int> hash;
map<int,bool> vis;

lt qpow(lt a,lt k,lt p)
{
    lt res=1;
    while(k>0)
    {
        if(k&1)res=(res*a)%p;
        a=(a*a)%p;
        k>>=1;
    }
    return res;
}

lt exgcd(lt a,lt b,lt &x,lt &y)
{
    if(b==0){x=1;y=0;return a;}
    lt g=exgcd(b,a%b,x,y);
    lt tp=x;
    x=y; y=tp-a/b*y;
    return g;
}

lt BSGS(lt a,lt b,lt p)
{
    hash.clear(); vis.clear();
    lt t=sqrt(p); b%=p;
    for(int j=0;j<=t;++j)
    {
        lt tt=b*qpow(a,j,p)%p;
        hash[tt]=j; vis[tt]=true;
    }
    a=qpow(a,t,p);
    if(a==0)return b==0?1:-1;
    for(int i=0;i<=t;++i)
    {
        lt tt=qpow(a,i,p);
        if(vis[tt]){
            int j=hash[tt];
            if(j>=0&&i*t-j>=0) return i*t-j;
        }
    }
    return -1;
}

int main()
{
    T=read();opt=read();
    while(T--)
    {
        lt a=read(),b=read(),p=read();
        if(opt==1)printf("%lld\n",qpow(a,b,p));
        else if(opt==2)
        {
            lt x,y,c=b;
            lt g=exgcd(a,p,x,y),bg=p/g;
            if(c%g!=0) printf("Orz, I cannot find x!\n");
            else printf("%lld\n",(x*(c/g)%bg+bg)%bg);
        }
        else if(opt==3)
        {
            lt ans=BSGS(a,b,p);
            if(ans==-1) printf("Orz, I cannot find x!\n");
            else printf("%lld\n",ans);
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/niiick/article/details/81781431
今日推荐