【SDOI 2010】古代猪文(组合计数)

题目链接:【BZOJ 1951】古代猪文

题目大意:给定正整数 q , n ( 1 q , n 10 9 ) ,求 q d | n C n d mod 999911659

q = 999911659 ,则上试结果为 0
否则,因为 999911659 是素数,所以 q , n 互素。由欧拉定理,得:

q d | n C n d q d | n C n d mod 999911658 mod 999911659

关键在于计算 d | n C n d mod 999911658 的值。
发现模数太大了,不能直接用Lucas定理求解。我们要换一种思路。

分解素因数得: 999911658 = 2 × 3 × 4679 × 35617 。我们只要分别计算 d | n C n d mod 2 , 3 , 4679 , 35617 的值,就可以用中国剩余定理或者exgcd计算出指数,从而用快速幂算出最终的答案。

#include <cstdio>
typedef long long ll;
const ll mod = 999911659;
const ll mo[] = {2, 3, 4679, 35617};
const ll m[] = {mod / 2, mod / 3, mod / 4679, mod / 35617};
const ll maxm = 35627;
ll n, g, cmo, cm, fac[maxm], inv[maxm], res, ans;
ll mpow(ll x, ll y, ll z) {
    ll u = 1;
    for (; y; y >>= 1) {
        if (y & 1) {
            u = x * u % z;
        }
        x = x * x % z;
    }
    return u;
}
ll calc(ll a, ll b) {
    if (b < 0 || b > a) {
        return 0;
    } else if (b == 0 || b == a) {
        return 1;
    } else {
        return fac[a] * inv[a - b] % cmo * inv[b] % cmo;
    }
}
ll lucas(ll a, ll b) {
    if (a | b) {
        return lucas(a / cmo, b / cmo) * calc(a % cmo, b % cmo) % cmo;
    } else {
        return 1;
    }
}
int main() {
    scanf("%lld %lld", &n, &g);
    if (g == mod) {
        puts("0");
        return 0;
    }
    for (int k = 0; k < 4; k++) {
        cmo = mo[k], cm = m[k];
        fac[0] = 1, inv[0] = 1;
        for (int i = 1; i < cmo; i++) {
            fac[i] = fac[i - 1] * i % cmo;
            inv[i] = mpow(fac[i], cmo - 2, cmo);
        }
        res = 0;
        for (int i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                if (i * i == n) {
                    res = (res + lucas(n, i)) % cmo;
                } else {
                    res = (res + lucas(n, i)) % cmo;
                    res = (res + lucas(n, n / i)) % cmo;
                }
            }
        }
        ll t = mpow(cm, cmo - 2, cmo) * cm % (mod - 1);
        ans = (ans + t * res % (mod - 1)) % (mod - 1);
    }
    printf("%lld\n", mpow(g, ans, mod));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42068627/article/details/80873747