[Codeforces 100633J]Ceizenpok’s formula

Description

求 \[C_n^m \mod p\]

\(1\leq m\leq n\leq 10^{18},2\leq p\leq 1000000\)

Solution

一般的 \(Lucas\) 是在模数 \(p\) 是质数的条件下适用的。我们来考虑 \(p\) 不是质数的条件。

我们对 \(p\) 进行唯一分解,记 \(p=p_1^{k_1}p_2^{k_2}\cdots p_q^{k_q}\) ,由于形同 \(p_i^{k_i}\) 的部分是互质的,显然我们可以用 \(CRT\) 合并。

列出方程组: \[\left\{ \begin{array}{c} ans\equiv c_1\pmod {{p_1}^{k_1}}\\ ans\equiv c_2\pmod {{p_2}^{k_2}}\\ ...\\ ans\equiv c_q\pmod {{p_q}^{k_q}}\\ \end{array} \right.\] ,对于每个 \(c_i\) ,表示 \(C_n^m\) 在 \(\mod p_i^{k_i}\) 下的结果。由解的唯一性,我们可以证明这个 \(ans\) 就是我们要求的。
根据 \(C_n^m=\frac{n!}{m!(n-m)!}\) 我们只要求出 \(n!\mod p_i^{k_i},m!\mod p_i^{k_i},(n-m)!\mod p_i^{k_i}\) ,再用逆元的那套理论就可以求 \(c_i\) 了。

考虑如何求 \(n!\mod p_i^{k_i}\) 。容易发现 \(n!=\left(\prod\limits_{j=1}^n j^{[p_i\nmid j]}\right)\cdot\left(p_i^{\left\lfloor\frac{n}{p_i}\right\rfloor}\right)\cdot\left(\left\lfloor\frac{n}{p_i}\right\rfloor\large! \right)\) 上述式子分为三个部分,第一个部分显然在模 \(p_i^{k_i}\) 下,是以 \(p_i^{k_i}\) 为周期的。可以周期内找循环节算,周期外的暴力算;第二部分可以直接算;第三部分可以递归求解。

另外注意的是求组合逆元的时候,存在阶乘中的某一个数可能还有 \(p_i\) 这个质因子,不能直接算。直接把 \(p_i\) 全部提出来,最后求完逆元后再补回去。求 \(n!\) 内质因子 \(p\) 的个数可以用 \(\sum\limits_{i=1}^{+\infty} \left\lfloor\frac{n}{p^i}\right\rfloor\) 来求。

Code

//It is made by Awson on 2018.2.10
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
void read(LL &x) {
    char ch; bool flag = 0;
    for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    x *= 1-2*flag;
}
void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); }

LL n, m, p;

LL quick_pow(LL a, LL b, LL p) {
    LL ans = 1;
    while (b) {
    if (b&1) ans = ans*a%p;
    b >>= 1, a = a*a%p;
    }
    return ans;
}
void ex_gcd(LL a, LL b, LL &x, LL &y) {
    if (b == 0) {x = 1, y = 0; return; }
    ex_gcd(b, a%b, x, y);
    LL t = x; x = y, y = t-a/b*y;
}
LL inv(LL a, LL p) {
    LL x, y; ex_gcd(a, p, x, y);
    return (x%p+p)%p;
}
LL mul(LL n, LL pi, LL pk) {
    if (!n) return 1;
    LL ans = 1;
    for (int i = 2; i <= pk; i++) if (i%pi != 0) ans = ans*i%pk;
    ans = quick_pow(ans, n/pi, pk);
    for (int i = 2; i <= n%pk; i++) if (i%pi != 0) ans = ans*i%pk;
    return ans*mul(n/pi, pi, pk)%pk;
}
LL C(LL n, LL m, LL pi, LL pk, LL p) {
    LL a = mul(n, pi, pk), b = mul(m, pi, pk), c = mul(n-m, pi, pk);
    LL k = 0;
    for (LL i = n; i; i /= pi) k += i/pi;
    for (LL i = m; i; i /= pi) k -= i/pi;
    for (LL i = n-m; i; i /= pi) k -= i/pi;
    return a*inv(b, pk)%pk*inv(c, pk)%pk*quick_pow(pi, k, pk)%pk;
}
LL ex_lucas(LL n, LL m, LL p) {
    LL ans = 0;
    for (LL i = 2, x = p; i <= x; i++)
    if (x%i == 0) {
        LL k = 1; while (x%i == 0) k *= i, x /= i;
        (ans += C(n, m, i, k, p)*(p/k)%p*inv(p/k, k)%p) %= p;
    }
    return ans;
}
void work() {
    read(n), read(m), read(p);
    writeln(ex_lucas(n, m, p));
}
int main() {
    work();
    return 0;
}

原文地址:https://www.cnblogs.com/NaVi-Awson/p/8438995.html

时间: 2024-10-11 18:18:48

[Codeforces 100633J]Ceizenpok’s formula的相关文章

CF.100633J.Ceizenpok&#39;s formula(扩展Lucas)

题目链接 ->扩展Lucas //求C_n^k%m #include <cstdio> typedef long long LL; LL FP(LL x,LL k,LL p) { LL t=1ll; for(; k; k>>=1,x=x*x%p) if(k&1) t=t*x%p; return t; } void Exgcd(LL a,LL b,LL &x,LL &y) { if(!b) x=1ll, y=0ll; else Exgcd(b,a%b,y

XV Open Cup named after E.V. Pankratiev. GP of Tatarstan

A. Survival Route 留坑. B. Dispersed parentheses $f[i][j][k]$表示长度为$i$,未匹配的左括号数为$j$,最多的未匹配左括号数为$k$的方案数.时间复杂度$O(n^3)$. #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int P=1000000009; const int N=310; int n,m

Codeforces Gym 100610 Problem E. Explicit Formula 水题

Problem E. Explicit Formula Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100610 Description Consider 10 Boolean variables x1, x2, x3, x4, x5, x6, x7, x8, x9, and x10. Consider all pairs and triplets of distinct variables amon

CodeForces 778B - Bitwise Formula

题意: 选择一个 m 位的二进制数字,总分为 n 个算式的答案之和.问得到最低分和最高分分别应该取哪个二进制数字 分析: 因为所有数字都是m位的,因为高位的权重大于地位 ,我们就从高到低考虑 ans 的每一位是取 0 还是取 1,统计该位的权重(即n个式子该位结果之和)即可. 1 #include <bits/stdc++.h> 2 using namespace std; 3 int n, m; 4 map<string, int> mp; 5 struct query{ 6 s

Codeforces 788A Functions again - 贪心

Something happened in Uzhlyandia again... There are riots on the streets... Famous Uzhlyandian superheroes Shean the Sheep and Stas the Giraffe were called in order to save the situation. Upon the arriving, they found that citizens are worried about

Codeforces Gym 100610 Problem A. Alien Communication Masterclass 构造

Problem A. Alien Communication Masterclass Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100610 Description Andrea is a famous science fiction writer, who runs masterclasses for her beloved readers. The most popular one is the

Codeforces Round #346 (Div. 2) (659A,659B,659C,659D(几何叉乘),659E(并查集))

Round House 题目链接: http://codeforces.com/problemset/problem/659/A 解题思路: The answer for the problem is calculated with a formula ((a?-?1?+?b)  n + n)  n + 1. Such solution has complexity O(1). There is also a solution with iterations, modelling every o

cf之路,1,Codeforces Round #345 (Div. 2)

 cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....       其实这个应该是昨天就写完的,不过没时间了,就留到了今天.. 地址:http://codeforces.com/contest/651/problem/A A. Joysticks time limit per test 1 second memory limit per test 256

Codeforces Round #614 (Div. 2) E. Xenon&#39;s Attack on the Gangs

On another floor of the A.R.C. Markland-N, the young man Simon "Xenon" Jackson, takes a break after finishing his project early (as always). Having a lot of free time, he decides to put on his legendary hacker "X" instinct and fight ag