B2242 [SDOI2011]计算器

这个题就是把三个数论基础合在了一起,算是一道比较全面的题.

1的时候就是快速幂

2的时候是exgcd求逆元,特殊的,只有两数互质才有逆元.

3就是bsgs啦,还是不太熟

题干:

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”之间有一个空格。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<map>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(register int i = a;i <= n;i++)
#define lv(i,a,n) for(register int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
#define int long long
const int INF = 1 << 30;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-') op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op) x = -x;
}
template <class T>
void write(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x >= 10) write(x / 10);
    putchar('0' + x % 10);
}
int t,k;
map <int,int> mp;
void work1(int y,int z,int p)
{
    int tot = 1;
    while(z)
    {
        if(z & 1)
        {
            tot *= y;
            tot %= p;
        }
        y *= y;
        y %= p;
        z >>= 1;
    }
    printf("%lld\n",tot);
}
int exgcd(int a,int b,int &x,int &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int t = exgcd(b,a % b,y,x);
    y -= (a / b * x);
    return t;
}
void work2(int y,int z,int p)
{
    int x,f;
    // z %= p;
    int d = exgcd(y,p,x,f);
    if(d != 1)
    {
        printf("Orz, I cannot find x!\n");
        return;
    }
    x = (x % p + p) % p;
    x = (x * z) % p;
    /*if(now == p)
    printf("Orz, I cannot find x!");
    else*/
    printf("%lld\n",x);
}
int qpow(int a,int b,int p)
{
    int tot = 1;
    while(b)
    {
        if(b & 1)
        {
            tot *= a;
            tot %= p;
        }
        a *= a;
        a %= p;
        b >>= 1;
    }
    return tot;
}
void work3(int a,int b,int p)
{
    if(a % p == 0)
    {
        printf("Orz, I cannot find x!\n");
        return;
    }
    mp.clear();
    int m = ceil(sqrt(p));
    int now = b % p,ans;
    mp[now] = 0;
    duke(i,1,m)
    {
        now = (now * a) % p;
        mp[now] = i;
    }
    int t = qpow(a,m,p);
    now = 1;
    int ok = 1;
    duke(i,1,m)
    {
        now = (now * t) % p;
        if(mp[now])
        {
            ans = i * m - mp[now];
            printf("%lld\n",(ans % p + p) % p);
            ok = 0;
            break;
        }
    }
    if(ok == 1)
    printf("Orz, I cannot find x!\n");
}
main()
{
    read(t);read(k);
    //cout<<t<<endl;
    duke(i,1,t)
    {
        int y,z,p;
        read(y);read(z);read(p);
        if(k == 1)
        {
            work1(y,z,p);
        }
        else if(k == 2)
        {
            work2(y,z,p);
        }
        else if(k == 3)
        {
            work3(y,z,p);
        }
        //cout<<i<<" "<<t<<endl;
    }
    return 0;
}

 

posted @ 2018-11-14 14:43  DukeLv  阅读(192)  评论(0编辑  收藏  举报