bzoj2242: [SDOI2011]计算器 BSGS+exgcd

你被要求设计一个计算器完成以下三项任务:
1、给定y,z,p,计算Y^Z Mod P 的值;(快速幂)
2、给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数;(exgcd)
3、给定y,z,p,计算满足Y^x ≡ Z ( mod P)的最小非负整数。(BSGS)

/**************************************************************
    Problem: 2242
    User: walfy
    Language: C++
    Result: Accepted
    Time:2244 ms
    Memory:3820 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double g=10.0,eps=1e-12;
const int N=100000+10,maxn=1000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
inline ll quick(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        a=a*a%p;b>>=1;
    }
    return ans;
}
inline ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b){x=1,y=0;return a;}
    ll ans=exgcd(b,a%b,x,y);
    ll t=x;x=y;y=t-a/b*y;
    return ans;
}
inline ll eg(ll y,ll z,ll p)
{
    ll x,k;
    exgcd(y,p,x,k);
    x=x*z/__gcd(y,p);
    ll b=p/__gcd(y,p);
    x=(x%b+b)%b;
    return x;
}
map<ll,ll>ma;
int main()
{
    int n,op;
    while(~scanf("%d%d",&n,&op))
    {
        ll y,z,p;
        for(int i=0;i<n;i++)
        {
            scanf("%lld%lld%lld",&y,&z,&p);
            if(op==1)printf("%lld\n",quick(y,z,p));
            else if(op==2)
            {
                if(z%__gcd(y,p)==0)printf("%lld\n",eg(y,z,p));
                else puts("Orz, I cannot find x!");
            }
            else
            {
                ll a=y,b=z;
                if(a%p==0)
                {
                    puts("Orz, I cannot find x!");
                    continue;
                }
                ma.clear();
                ll m=ceil(sqrt(p));
                ll now=b%p;
                ma[now]=0;
                for(int i=1;i<=m;i++)
                {
                    now=(now*a)%p;
                    ma[now]=i;
                }
                ll ans=-1,t=quick(a,m,p);now=1;
                for(int i=1;i<=m;i++)
                {
                    now=now*t%p;
                    if(ma[now])
                    {
                        ans=i*m-ma[now];
                        break;
                    }
                }
                if(ans!=-1)printf("%lld\n",(ans%p+p)%p);
                else puts("Orz, I cannot find x!");
            }
        }
    }
    return 0;
}
/***********************
 
***********************/
posted @ 2018-07-07 00:25  walfy  阅读(169)  评论(0编辑  收藏  举报