题意:求
\[g^{\sum_{k\mid n}{n\choose k}} \]对 \(999911659\) 取模。
\(1\le n,g\le 10^9\)。
思路:
首先根据欧拉定理,题目转化为求 \(\displaystyle\sum_{k\mid n}{n\choose k}\) 对 \(999911658\) 取模的值。
模数为合数不是很好做,因式分解发现 \(999911658=2\times 3\times 4679\times35617\),考虑中国剩余定理,分别求出 \(\displaystyle\sum_{k\mid n}{n\choose k}\) 模 \(2,3,4679,35617\) 的值,用中国剩余定理合并即可。
由于 \(n\) 的因数个数是 \(\mathcal{O}(\sqrt{n})\) 的,直接暴力枚举 \(k\) 然后卢卡斯定理算组合数即可。
一道挺好的综合练习题。
#include <iostream>
using namespace std;
const int kM = 999911659;
const int kL[4] = {2, 3, 4679, 35617};
int n, g;
int P(int b, int e, int p) {
int s = 1;
for (; e; e >>= 1, b = 1LL * b * b % p) {
(e & 1) && (s = 1LL * s * b % p);
}
return s;
}
struct Solver {
static const int kP = 3.6e4 + 1;
int p, vf[kP], ivf[kP];
Solver(int p) : p(p) {
vf[0] = 1;
for (int i = 1; i < p; ++i) {
vf[i] = 1LL * vf[i - 1] * i % p;
}
ivf[p - 1] = P(vf[p - 1], p - 2, p);
for (int i = p - 1; i >= 1; --i) {
ivf[i - 1] = 1LL * ivf[i] * i % p;
}
}
int C(int n, int m) {
if (n < p && m < p) {
return n >= m ? 1LL * vf[n] * ivf[m] % p * ivf[n - m] % p : 0;
}
return 1LL * C(n / p, m / p) * C(n % p, m % p) % p;
}
int operator()() {
int ans = 0;
for (int k = 1; k * k <= n; ++k) {
if (n % k == 0) {
ans = (ans + C(n, k)) % p;
if (k != n / k) {
ans = (ans + C(n, n / k)) % p;
}
}
}
return ans;
}
};
int main() {
ios_base::sync_with_stdio(0), cin.tie(0);
cin >> n >> g;
g %= kM;
if (!g) {
cout << '0';
return 0;
}
int s = 0;
for (int i = 0; i < 4; ++i) {
int vm = (kM - 1) / kL[i];
int im = P(vm, kL[i] - 2, kL[i]);
s = (s + 1LL * Solver(kL[i])() * vm % (kM - 1) * im % (kM - 1)) % (kM - 1);
}
cout << P(g, s, kM);
return 0;
}
标签:ivf,4679,vf,int,题解,sum,1LL,猪文,P2480
From: https://www.cnblogs.com/bykem/p/17432782.html