• bzoj2242 [SDOI2011]计算器


    2242: [SDOI2011]计算器

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 4699  Solved: 1782
    [Submit][Status][Discuss]

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

    Sample Input

    【样例输入1】
    3 1
    2 1 3
    2 2 3
    2 3 3
    【样例输入2】
    3 2
    2 1 3
    2 2 3
    2 3 3
    【数据规模和约定】
    对于100%的数据,1<=y,z,p<=10^9,为质数,1<=T<=10。

    Sample Output

    【样例输出1】
    2
    1
    2
    【样例输出2】
    2
    1
    0

    HINT

    Source

    分析:几个算法的大合集.对于第一组询问,快速幂就好了.对于第二组询问,相当于解一个同余方程,用扩展欧几里得算法搞一搞就好了.对于第三组询问,用BGSG来做,关于BGSG算法的详细讲解,可以参看:传送门.
    #include <cstdio>
    #include <cmath>
    #include <map>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    int T, K;
    typedef long long ll;
    ll y, z, p, x, block;
    map <ll, ll> m;
    
    ll qpow(ll a, ll b, ll mod)
    {
        ll res = 1;
        while (b)
        {
            if (b & 1)
                res = (res * a) % mod;
            a = (a * a) % mod;
            b >>= 1;
        }
        return res;
    }
    
    void solve1()
    {
        scanf("%lld%lld%lld", &y, &z, &p);
        printf("%lld
    ", qpow(y, z, p));
    }
    
    ll exgcd(ll a, ll b, ll &x, ll &y)
    {
        if (!b)
        {
            x = 1;
            y = 0;
            return a;
        }
        ll temp = exgcd(b, a % b, x, y);
        ll t = x;
        x = y;
        y = t - (a / b) * y;
        return temp;
    }
    
    void solve2()
    {
        scanf("%lld%lld%lld", &y, &z, &p);
        ll tx, ty, td;
        td = exgcd(y, p, tx, ty);
        if (z % td != 0)
            puts("Orz, I cannot find x!");
        else
        {
            tx = tx * (z / td) % p;
            ll mmod = p / td;
            tx = (tx % mmod + mmod) % mmod;
            printf("%lld
    ", tx);
        }
    }
    
    void solve3()
    {
        scanf("%lld%lld%lld", &y, &z, &p);
        m.clear();
        if (y % p == 0)
        {
            puts("Orz, I cannot find x!");
            return;
        }
        else
        {
            block = ceil(sqrt(p));
            ll ans;
            for (int i = 0; i <= block; i++)
            {
                if (i == 0)
                {
                    ans = z % p;
                    m[ans] = i;
                    continue;
                }
                ans = (ans * y) % p;
                m[ans] = i;
            }
            ll t = qpow(y, block, p); 
            ans = 1;
            for (int i = 1; i <= block; i++)
            {
                ans = (ans * t) % p;
                if (m[ans])
                {
                    ll t = i * block - m[ans];
                    printf("%lld
    ", (t % p + p) % p);
                    return;
                }
            }
        }
        puts("Orz, I cannot find x!");
    }
    
    int main()
    {
        scanf("%d%d", &T, &K);
        while (T--)
        {
            if (K == 1)
                solve1();
            if (K == 2)
                solve2();
            if (K == 3)
                solve3();
        }
    
        return 0;
    }
     
  • 相关阅读:
    个人冲刺二(7)
    个人冲刺二(6)
    个人冲刺二(5)
    个人冲刺二(4)
    对称二叉树 · symmetric binary tree
    108 Convert Sorted Array to Binary Search Tree数组变成高度平衡的二叉树
    530.Minimum Absolute Difference in BST 二叉搜索树中的最小差的绝对值
    pp 集成工程师 mism师兄问一问
    17. Merge Two Binary Trees 融合二叉树
    270. Closest Binary Search Tree Value 二叉搜索树中,距离目标值最近的节点
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7879717.html
Copyright © 2020-2023  润新知