luogu P2480 [SDOI2010]古代猪文
https://www.luogu.com.cn/problem/P2480
读完题后不难得到要求的实际上是
\[g^{\sum_{d|n}\binom{n}{d}} \mod p
\]
难点在求上面那个东西\(\mod (p-1)\)
直接\(Lucas\)显然会寄,把\(p-1\)质因数分解一下可以得到
\(999911658=2\times3\times4679\times35617\)
于是乎对于每个质数分别跑一遍,最后再用中国剩余定理合并起来即可
code:
#include<bits/stdc++.h>
#define ll long long
#define N 2000050
using namespace std;
const int mod = 999911659;
int b[7] = {0, 2, 3, 4679, 35617};
ll qpow(ll x, ll y, int p) {
ll ret = 1;
for(; y; y >>= 1, x = x * x % p) if(y & 1) ret = ret * x % p;
return ret;
}
ll fac[N], ifac[N];
void init(int n, int p) { n --;
fac[0] = 1;
for(int i = 1; i <= n; i ++) fac[i] = fac[i - 1] * i % p;
ifac[n] = qpow(fac[n], p - 2, p);
for(int i = n - 1; i >= 0; i --) ifac[i] = ifac[i + 1] * (i + 1) % p;
}
ll C(int n, int m, int p) {
if(n < m) return 0;
return fac[n] * ifac[m] % p * ifac[n - m] % p;
}
ll Lucas(int n, int m, int p) {
if(!m) return 1;
return Lucas(n / p, m / p, p) % p * C(n % p, m % p, p) % p;
}
ll ans = 0, a[N];
void crt() {
int M = mod - 1;
for(int i = 1; i <= 4; i ++) {
int mi = M / b[i];
(ans += 1ll * a[i] * mi % M * qpow(mi, b[i] - 2, b[i]) % M) %= M;
}
}
int n, g;
int main() {
scanf("%d%d", &n, &g);
if(g % mod == 0) {
printf("0");
return 0;
}
for(int i = 1; i <= 4; i ++) {
init(b[i], b[i]);
for(int j = 1; j * j <= n; j ++) if(n % j == 0) {
a[i] = (a[i] + Lucas(n, j, b[i])) % b[i];
// printf("%d %d %d %lld\n", n, j, b[i], Lucas(n, j, b[i]));
if(j * j != n) a[i] = (a[i] + Lucas(n, n / j, b[i])) % b[i];
}
}
//for(int i = 1; i <= 4; i ++) printf("%lld %d\n", a[i], b[i]);
crt();
//printf("%lld\n", ans);
printf("%lld", qpow(g, ans, mod));
return 0;
}