Description
给定 n,gn,gn,g,定义 f(n)=∑k∣n(nk)f(n)=\sum\limits_{k\mid n}\binom{n}{k}f(n)=k∣n∑(kn),求 gf(n) mod 999911659g^{f(n)}\bmod 999911659gf(n)mod999911659 的值.
Limitations
1≤n,g≤1091\le n,g\le 10^91≤n,g≤109
1s,125MB1\text{s},125\text{MB}1s,125MB
Solution
首先,如果 g=999911659g=999911659g=999911659,直接特判掉输出 000.
接下来,根据欧拉定理,我们需要求 f(n) mod 999911658f(n)\bmod 999911658f(n)mod999911658.
虽然可以暴力枚举 n\sqrt nn 个因数求答案,但是 999911658∉P999911658\notin \mathbb{P}999911658∈/P,在求组合数时无法直接使用 Lucas 定理.
注意到 999911658=2×3×4679×35617999911658=2\times 3\times 4679\times 35617999911658=2×3×4679×35617,无平方因子.
现在我们就可以用 Lucas 分别求出 f(n)f(n)f(n) 模这四个数的结果 a1,a2,a3,a4a_1,a_2,a_3,a_4a1,a2,a3,a4,然后用 CRT 解如下方程:
{x≡a1(mod2)x≡a2(mod3)x≡a3(mod4679)x≡a4(mod35617)
\begin{equation*}
\begin{cases}
x\equiv a_1 \pmod 2 \\
x\equiv a_2 \pmod 3 \\
x\equiv a_3 \pmod {4679} \\
x\equiv a_4 \pmod {35617}
\end{cases}
\end{equation*}
⎩⎨⎧x≡a1(mod2)x≡a2(mod3)x≡a3(mod4679)x≡a4(mod35617)
即可得到 f(n) mod 999911658f(n)\bmod 999911658f(n)mod999911658,再用一次快速幂即可求得答案.
Code
2.14KB,94ms,864KB (C++20 with O2)2.14\text{KB},94\text{ms},864\text{KB}\;\texttt{(C++20 with O2)}2.14KB,94ms,864KB(C++20 with O2)
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;
template<class T>
bool chmax(T &a, const T &b){
if(a < b){ a = b; return true; }
return false;
}
template<class T>
bool chmin(T &a, const T &b){
if(a > b){ a = b; return true; }
return false;
}
constexpr int P = 999911659;
inline int add(int a, int b, int mod) { return (a + b >= mod) ? (a + b - mod) : (a + b); }
inline int mul(int a, int b, int mod) { return 1LL * a * b % mod; }
inline int qpow(int a, int b, int mod) {
int res = 1;
for (; b; b >>= 1, a = mul(a, a, mod))
if (b & 1) res = mul(res, a, mod);
return res;
}
struct Lucas {
int P;
vector<int> fac, ifac;
inline Lucas() {}
inline void init(int p) {
P = p;
fac.resize(P);
ifac.resize(P);
fac[0] = 1;
for (int i = 1; i < P; ++i) {
fac[i] = mul(fac[i - 1], i, P);
}
ifac[P - 1] = qpow(fac[P - 1], P - 2, P);
for (int i = P - 2; i >= 0; --i) {
ifac[i] = mul(ifac[i + 1], i + 1, P);
}
}
inline int comb(int n, int m) {
if (m < 0 || m > n) return 0;
return mul(fac[n], mul(ifac[m], ifac[n - m], P), P);
}
inline int lucas(int n, int m) {
if (m == 0) return 1;
return mul(comb(n % P, m % P), lucas(n / P, m / P), P);
}
};
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, g; cin >> n >> g;
if (g == P) {
cout << 0;
return 0;
}
array<Lucas, 4> L;
L[0].init(2), L[1].init(3);
L[2].init(4679), L[3].init(35617);
array<int, 4> sum; sum.fill(0);
for (int i = 1; i <= n / i; i++)
if (n % i == 0)
for (int j = 0; j < 4; j++) {
sum[j] = add(sum[j], L[j].lucas(n, i), L[j].P);
if (i != n / i) sum[j] = add(sum[j], L[j].lucas(n, n / i), L[j].P);
}
int ans = 0;
for (int i = 0; i < 4; i++) {
int M = (P - 1) / L[i].P, Minv = qpow(M, L[i].P - 2, L[i].P);
ans = add(ans, mul(mul(M, Minv, P - 1), sum[i], P - 1), P - 1);
}
cout << qpow(g, ans, P);
return 0;
}
25万+

被折叠的 条评论
为什么被折叠?



