P5605 小 A 与两位神仙 题解

· · 题解

分析

前置芝士

化简

求解

AC 代码

#include <bits/stdc++.h>
#define int long long
#define inf 1e9
using namespace std;
int n, m, phi, x, y;
map<int, bool> mp;

inline void read(int &x) {
    char ch = x = 0;
    int m = 1;
    while (ch < '0' || ch > '9') {
        ch = getchar();
        if (ch == '-')
            m *= -1;
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + ch - 48;
        ch = getchar();
    }
    x *= m;
    return ;
}

int seed;
inline int rnd(int x) {
    int a = rand() % 1145 + 1;
    x *= a;
    x ^= x << 13;
    x ^= x >> 7;
    x ^= x << 17;
    x /= a;
    return abs(x);
}

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

inline int ksmi(__int128 a, int b, int mod) {
    int s = 1;
    while (b) {
        if (b & 1) s = a * s % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return s;
}

inline bool mr(int n) {
    if (n < 3 || n % 2 == 0) return n == 2;
    int r = n - 1, d = 0;
    while ((r & 1) == 0) {
        r >>= 1;
        d++;
    }
    int a, v;
    for (int i = 1; i <= 20; i++) {
        a = seed = rnd(seed);
        a = a % (n - 2) + 2;
        v = ksmi(a, r, n);
        if (v == 1) continue;
        for (int j = 0; j <= d; j++) {
            if (j == d) return 0;
            if (v == n - 1) break;
            v = (__int128)v * v % n;
        }
    }
    return 1;
}

inline int pol(int n) {
    int s = 0, t = 0, now = 1, c = seed = rnd(seed);
    c = c % (n - 1) + 1;
    int k = 1;
    while (1) {
        for (int j = 1; j <= k; j++) {
            t = ((__int128)t * t + c) % n;
            now = (__int128)now * abs(s - t) % n;
            if ((j % 127 == 0 || j == k) && gcd(now, n) > 1) return gcd(now, n);
        }
        s = t;
        k <<= 1;
    }
}

void fac(int n) {
    if (n == 1) return;
    if (mr(n)) {
        mp[n] = 1;
        return ;
    }
    int p = n;
    while (p == n) p = pol(n);
    while (n % p == 0) n /= p;
    fac(p);
    fac(n);
    return ;
}

signed main() {
    srand((unsigned)time(0));
    seed = rand() * rand();
    read(m), read(n);
    fac(m);
    int pri = mp.begin() -> first;
    phi = m - (m / pri);
    mp.clear();
    fac(phi);
    int ordx, ordy, now;
    while (n--) {
        read(x), read(y);
        ordx = ordy = phi;
        for (auto it : mp) {
            now = it.first;
            while (ordx % now == 0 && ksmi(x, ordx / now, m) == 1) ordx /= now;
            while (ordy % now == 0 && ksmi(y, ordy / now, m) == 1) ordy /= now;
        }
        if (ordx % ordy) printf("No\n");
        else printf("Yes\n");
    }
    return 0;
}