zoukankan      html  css  js  c++  java
  • 【SDOI2011】计算器

    Description

    给定$y, z, p$,求$x=y^{z} mod p$或$xyequiv z pmod p$或$y^xequiv zpmod p$中x的值

    Solution

    第一个式子我们可以直接用快速幂求解答案。时间复杂度$O(log_{2}z)$

    第二个式子我们可以变形为$xy+Yp=z$,然后用扩展欧几里得算法求出$xy+Yp=gcd(y,p)$的解,然后利用裴蜀定理判断是否有解即可。

    第三个式子我们可以应用BSGS算法求解。详细的解释在这里

    Code

     1 #include <cstdio>
     2 #include <map>
     3 #include <cmath>
     4 using namespace std;
     5 typedef long long ll;
     6 ll qpow(ll a, ll b, ll p) {
     7     ll ret = 1;
     8     while (b) {
     9         if (b & 1) ret = (ret * a) % p;
    10         a = a * a % p;
    11         b >>= 1;
    12     }
    13     return ret % p;
    14 }
    15 ll exgcd(ll a, ll b, ll &x, ll &y) {
    16     if (!b) {
    17         x = 1, y = 0;
    18         return a;
    19     }
    20     ll gcd = exgcd(b, a % b, x, y);
    21     ll x2 = x, y2 = y;
    22     x = y2;
    23     y = x2 - (a / b) * y2;
    24     return gcd;
    25 }
    26 map <ll, ll> h;
    27 ll BSGS(ll a, ll b, ll p) {
    28     h.clear();
    29     b %= p;
    30     ll t = (ll)sqrt(p) + 1;
    31     for (register int j = 0; j < t; ++j) {
    32         ll val = (ll)b * qpow(a, j, p) % p;
    33         h[val] = j;
    34     }
    35     a = qpow(a, t, p);
    36     if (a == 0) return b == 0 ? 1 : -1;
    37     for (register int i = 0; i <= t; ++i) {
    38         ll val = qpow(a, i, p);
    39         ll j = h.find(val) == h.end() ? -1 : h[val];
    40         if (j >= 0 && i * t - j >= 0) return i * t - j;
    41     }
    42     return -1;
    43 }
    44 int n, k;
    45 int main() {
    46     ll y = 0, z = 0, p = 0;
    47     scanf("%d%d", &n, &k);
    48     if (k == 1) 
    49         while (n--) {
    50             scanf("%lld%lld%lld", &y, &z, &p);
    51             printf("%lld
    ", qpow(y, z, p));
    52         }
    53     else if (k == 2) 
    54         while (n--) {
    55             scanf("%lld%lld%lld", &y, &z, &p);
    56             ll x = 0, yy = 0;
    57             ll ret = exgcd(y, p, x, yy);
    58             if (z % ret != 0) {puts("Orz, I cannot find x!"); continue ;}
    59             ll now = p / ret;
    60             while (x < 0) x += now;
    61             printf("%lld
    ", (x * (z / ret) % now) + now % now);
    62         }
    63     else 
    64         while (n--) {
    65             scanf("%lld%lld%lld", &y, &z, &p);
    66             ll ret = BSGS(y, z, p);
    67             if (ret == -1) puts("Orz, I cannot find x!");
    68             else printf("%lld
    ", ret);
    69         }
    70     return 0;
    71 }
    AC Code
  • 相关阅读:
    联考20200604 T2 宝石
    联考20200604 T1 旅游
    联考20200603 T2 排列
    [HAOI2017]八纵八横
    联考20200603 T1 解码
    [POI2011]KON-Conspiracy
    CF917D Stranger Trees
    CF1278F Cards
    CF809E Surprise me!
    NOI2016 循环之美
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11332183.html
Copyright © 2011-2022 走看看