古代猪文

数学真的好ex

题面

(1 leqslant q, n leqslant 10^9), 计算 (q^{sum_{d|n}C_n^d mod 999911658}(mod 999911659))

题解

注意到指数取模的非质数, 所以我们可以分别取模, 最后用中国剩余定理合并

(C_n^m)时, 使用Lucas定理

ps:如果想要化简, 根据欧拉定理去化简

const int mod[] = {2, 3, 4679, 35617, 999911659, 999911658};

int n, m, _, k;
int inv[N] = {0, 1}, a[N] = {1, 1}, b[N] = {1, 1};
VI fa;

int power(int a, int b, int mod) {
    int ans = 1;
    for (; b; b >>= 1, a = (ll)a * a % mod)
        if (b & 1) ans = (ll)ans * a % mod;
    return ans;
}

int exgcd(int a, int b, int& x, int& y) {
    if (b == 0) { x = 1, y = 0; return a; }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

int C(int x, int y, int p) {
    if (y > x) return 0;
    return (ll)a[x] * b[y] % p * b[x - y] % p;
}

int lucas(int x, int y, int p) {
    if (y == 0) return 1;
    return (ll)C(x % p, y % p, p) * lucas(x / p, y / p, p) % p;
}

void work(int p) {
    rep (i, 2, p) {
        inv[i] = (ll)(p - p / i) * inv[p % i] % p;
        a[i] = (ll)a[i - 1] * i % p;
        b[i] = (ll)b[i - 1] * inv[i] % p;
    }
}

int cal(int p) {
    work(p);
    int res = 0;
    for (int i : fa) res = (res + (ll)lucas(n, i, p)) % p;
    return res;
}

void init() {
    for (int i = 1; i * i <= n; ++i)
        if (n % i == 0) {
            fa.pb(i);
            if (i * i == n) break;
            fa.pb(n / i);
        }
}

int main() {
    IO;
    cin >> n >> m;
    if (m == mod[4]) { cout << 0; return 0; }
    init();

    rep (i, 0, 3) {
        int x, y, m = mod[4] / mod[i], a = cal(mod[i]);
        exgcd(m, mod[i], x, y);
        k = (k + ((ll)a * m % mod[5] * x % mod[5] + mod[5]) % mod[5]) % mod[5];
    }

    cout << power(m, k, mod[4]);
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/13448260.html