BZOJ2242 [SDOI2011]计算器 题解&代码

来源:互联网 发布:航天科工智慧 java 编辑:程序博客网 时间:2024/06/12 21:05

题意:有三种要求:
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显然是快速幂了,纯模板
2是扩展欧几里得(exgcd),求满足xy-pk=z的最小x(k任意)
3利用了费马小定理的性质a^(p-1)≡1(mod p),然后分块降复杂度(太麻烦懒得写直接抄黄学长代码…捂脸)

/**************************************************************    Problem: 2242    User: Rainbow6174    Language: C++    Result: Accepted    Time:2028 ms    Memory:3272 kb****************************************************************/#include<iostream>#include<cstdio>#include<cmath>#include<map>#define LL long longusing namespace std;int T,k;map<int,int> vis;LL y,z,x,a,b,m,t,mod,temp,flag;LL pow(LL base,LL x){    LL ret = 1;    base %= mod;    while(x)    {        if(x & 1)ret *= base,ret %= mod;        base *= base;        base %= mod;        x >>= 1;    }    return ret;}LL gcd(LL x,LL y){    if(!y)return x;    return gcd(y,x%y);}LL exgcd(LL x,LL y){    if(!y)    {        a=1,b=0;        return x;    }    int ret=exgcd(y,x%y);    //cout<<a<<' '<<b<<' '<<x<<' '<<y<<endl;    temp=a;    a=b;    b=temp-(x/y)*b;    return ret;}int main(void){    //freopen("calc.in","r",stdin);    //freopen("calc.out","w",stdout);    scanf("%d%d",&T,&k);    while(T--)    {        scanf("%lld%lld%lld",&y,&z,&mod);        if(k==1)printf("%lld\n",pow(y,z));        y%=mod;        z%=mod;        if(k==2)        {            if(!z)            {                printf("0\n");                continue;            }            if(!y || gcd(y,mod)>z)            {                printf("Orz, I cannot find x!\n");                continue;            }            //cout<<y<<' '<<mod<<endl;            exgcd(y,mod);            a+=mod;            a%=mod;            a*=z/gcd(y,mod);            a%=mod;            printf("%lld\n",a);        }        if(k==3)        {            flag=0;            if(!y)            {                if(!z)puts("1");                else puts("Orz, I cannot find x!");                continue;            }            vis.clear();            LL a=ceil(sqrt(mod)),t=1;            vis[1]=a+1;            for(LL i=1;i<a;i++)            {                t=t*y%mod;                if(!vis[t])vis[t]=i;            }            temp=pow(y,mod-a-1),b=1;            for(LL i=0;i<a;i++)            {                int temp1=vis[z*b%mod];                if(temp1)                {                    if(temp1==a+1)temp1=0;                    printf("%lld\n",i*a+temp1);                    flag=1;                    break;                }                b=b*temp%mod;            }            if(!flag)puts("Orz, I cannot find x!");        }    }}
0 0
原创粉丝点击