https://www.acwing.com/problem/content/215/
题意
给定整数 q , n ( 1 ≤ q , n ≤ 1 0 9 ) q,n(1 \leq q,n \leq 10^9) q,n(1≤q,n≤109),计算
q ∑ d ∣ n C n d m o d 999911659 q^{\sum_{d|n} C_n^d}mod 999911659 q∑d∣nCndmod999911659
思路
首先,进行一个特判。当
q
=
999911659
q=999911659
q=999911659,显然答案为0。
否则由于999911659是一个质数,故其与q互质,满足欧拉定理的条件。
之后,由欧拉定理的推论
若正整数 a , n a,n a,n互质,则对于任意整数 a a a,有 a b ≡ a ( b m o d φ ( n ) ) ( m o d n ) a^b \equiv a^{(b \; mod \; \varphi(n))}(mod \; n) ab≡a(bmodφ(n))(modn)
可以得到
q ∑ d ∣ n C n d ≡ q ∑ d ∣ n C n d m o d 999911658 ( m o d 999911659 ) q^{\sum_{d|n}C_n^d} \equiv {q^{\sum_{d|n}C_n^d mod \; 999911658}}(mod \; 999911659) q∑d∣nCnd≡q∑d∣nCndmod999911658(mod999911659)
注意到999911658显然是一个合数,我们尝试将它分解质因数得到
999911658 = 2 × 3 × 4679 × 35617 999911658=2 \times 3 \times 4679 \times 35617 999911658=2×3×4679×35617
它们的次数全都是1。
接下来,由于问题要求我们求 d ∣ n d|n d∣n,因此我们可以根据这些质因数枚举999911658的约数。对每一个约数,可以利用Lucas定理
C n m ≡ C n m o d p m m o d p ∗ C n p m p ( m o d p ) C_n^m \equiv C_{n \; mod \; p}^{m \; mod \; p}* C_{\frac{n}{p}}^{\frac{m}{p}}(mod \; p) Cnm≡Cnmodpmmodp∗Cpnpm(modp)
求出组合数 C n d C_n^d Cnd,并计算出 ∑ d ∣ n C n d \sum d|n C_n^d ∑d∣nCnd对四个质因数取模的结果,记为 a 1 ∼ a 4 a_1 \sim a_4 a1∼a4
最后,利用中国剩余定理
设 m 1 ∼ m n m_1 \sim m_n m1∼mn是两两互质的整数, m = ∏ i = 1 n m i , M i = m m i m = \prod _{i=1}^nm_i,M_i=\frac{m}{m_i} m=∏i=1nmi,Mi=mim, t i t_i ti是线性同余方程 M i t i ≡ 1 ( m o d m i ) M_it_i \equiv 1(mod \; m_i) Miti≡1(modmi)。对于任意的 n n n个整数 a 1 ∼ a n a_1 \sim a_n a1∼an,方程组
{ x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) … x ≡ a n ( m o d m n ) \begin{cases} x \equiv a_1(mod \; m_1)\\ x \equiv a_2(mod \; m_2)\\ \dots\\ x \equiv a_n(mod \; m_n) \end{cases} ⎩ ⎨ ⎧x≡a1(modm1)x≡a2(modm2)…x≡an(modmn)
有整数解为 x = ∑ i = 1 n a i M i t i x=\sum_{i=1}^{n}a_iM_it_i x=∑i=1naiMiti
解出线性方程组
{ x m o d 2 = a 1 x m o d 3 = a 2 x m o d 4679 = a 3 x m o d 35617 = a 4 \begin{cases} x \; mod \; 2 \; = \; a_1 \\ x \; mod \; 3 \; = \; a_2 \\ x \; mod \; 4679 \; = \; a_3 \\ x \; mod \; 35617 \; = \; a_4 \end{cases} ⎩ ⎨ ⎧xmod2=a1xmod3=a2xmod4679=a3xmod35617=a4
-
这一步是可以转化成CRT的目标形式,即 x ≡ a i ( m o d m i ) x \; \equiv \; a_i(mod \; m_i) x≡ai(modmi)的。这是因为 x m o d m i = a i x \; mod \; m_i = a_i xmodmi=ai代表 a i m o d m i ≡ a i a_i \; mod \; m_i \equiv \; a_i aimodmi≡ai,又 x m o d m i = a i x \; mod \; m_i=a_i xmodmi=ai。
得到 ∑ d ∣ n C n d m o d 999911658 \sum _{d|n}^{C_n^d} mod \; 999911658 ∑d∣nCndmod999911658的最小非负整数解 x x x,然后利用快速幂求 q x q^x qx即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int a[4] = {2, 3, 4679, 35617};
int factorials[36000], b[4], n, g, ans, x, y, mod = 999911658; // b中存储了CRT右侧的数字
int power(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1)
res = (ll)res * a % mod;
b >>= 1;
a = (ll)a * a % mod;
}
return res;
}
void exgcd(int a, int b, int &x, int &y)
{
if (!b)
{
x = 1, y = 0;
return;
}
exgcd(b, a % b, x, y);
int z = x;
x = y;
y = z - y * (a / b);
}
int inv(int a, int p) // 求逆元
{
int x, y;
exgcd(a, p, x, y);
return (x % p + p) % p;
}
int calc(int x, int mod) // lucas定理求组合数
{
int ans = 1, y, a, b;
for (y = n; x; x /= mod, y /= mod)
{
a = x % mod, b = y % mod; // 余数
ans = (ll)ans * factorials[b] % mod * inv(factorials[a], mod) % mod * inv(b < a ? 0 : factorials[b - a], mod) % mod; // 求m!/n!(m-n)!
}
return ans;
}
int main()
{
cin >> n >> g;
g %= mod + 1;
if (!g)
{ // 特判999911659
cout << 0 << endl;
return 0;
}
for (int i = factorials[0] = 1; i <= a[3]; i++)
{
// 阶乘预处理
factorials[i] = (ll)factorials[i - 1] * i % mod;
}
for (int i = 1; i * i <= n; i++) // 枚举质因数可构成的约数
{
if (n % i == 0) // i是约数
{
for (int j = 0; j < 4; j++)
b[j] = (b[j] + calc(i, a[j])) % a[j]; // 求C_n^i
if (i * i != n)
{
for (int j = 0; j < 4; j++)
b[j] = (b[j] + calc(n / i, a[j])) % a[j]; // 枚举约数 并计算相应的组合数
}
}
}
for (int i = 0; i < 4; i++)
{
exgcd(mod / a[i], a[i], x, y); // CRT
ans = (ans + (ll)x * (mod / a[i]) % mod * b[i]) % mod;
}
ans = (ans + mod) % mod, mod++; // 映射到最小非负值
ans = power(g, ans); // q^x
cout << ans << endl;
return 0;
}