[bzoj2242][SDOI2011]计算器

来自FallDream的博客,未经允许,请勿转载,谢谢。


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

第一问快速幂 第二问exgcd 第三问bsgs

然后bsgs的时候感觉写$y^{ax-b}=z$比较舒服,这样$y^b$可以直接乘到右边

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n,k,y,z,p,MN;
ll a,b;
map<int,int> mp; 

int pow(int x,int k,int mod)
{
    if(mod==1) return 0;
    int sum=1;
    for(;k;k>>=1,x=1LL*x*x%mod)
        if(k&1) sum=1LL*sum*x%mod;
    return sum;
} 

int exgcd(int a,int b,ll&x,ll&y)
{
    if(!b){x=1;y=0;return a;}
    int c=exgcd(b,a%b,x,y);
    ll t=x;x=y;y=t-(a/b)*x;
    return c;
}

int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(k==1)
        {
            for(int i=1;i<=n;i++)
                y=read(),z=read(),p=read(),printf("%d\n",pow(y,z,p));
        }
        if(k==2)
        {
            for(int i=1;i<=n;i++)
            {
                y=read(),z=read(),p=read();
                int c=exgcd(y,p,a,b);
                if(z%c) puts("Orz, I cannot find x!");
                else y/=c,z/=c,p/=c,printf("%lld\n",((a*z/c)%p+p)%p);
            }
        }
        if(k==3)
        {
            for(int i=1;i<=n;i++)
            {
                mp.clear();
                y=read();z=read();p=read();y%=p;MN=ceil(sqrt(p));
                if(!y&&!z)puts("1");else
                if(!y)puts("Orz, I cannot find x!");
                else if(p==1) puts("0");
                else
                {
                    int times=pow(y,MN,p);bool flag=0;
                    for(int j=0,k=z%p;j<=MN;j++,k=1LL*k*y%p)
                        mp[k]=j;
                    for(int j=1,k=times;j<MN;j++,k=1LL*k*times%p)
                        if(mp[k]) {flag=1,printf("%lld\n",1LL*j*MN-mp[k]);break;}
                    if(!flag) puts("Orz, I cannot find x!");
                }
            }
        }
    }
    return 0;
}

 

posted @ 2017-04-18 08:59  FallDream  阅读(189)  评论(0编辑  收藏  举报