[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/pk, 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;
}
[Codeforces 100633J]Ceizenpok’s formula的更多相关文章
- Codeforces.100633J.Ceizenpok's formula(扩展Lucas)
题目链接 ->扩展Lucas //求C_n^k%m #include <cstdio> typedef long long LL; LL FP(LL x,LL k,LL p) { L ...
- codeforces Gym - 100633J Ceizenpok’s formula
拓展Lucas #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring ...
- 2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理)
J. Ceizenpok’s formula time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- GYM100633J. Ceizenpok’s formula 扩展lucas模板
J. Ceizenpok’s formula time limit per test 2.0 s memory limit per test 256 MB input standard input o ...
- Ceizenpok’s formula Gym - 100633J 扩展Lucas定理 + 中国剩余定理
http://codeforces.com/gym/100633/problem/J 其实这个解法不难学的,不需要太多的数学.但是证明的话,我可能给不了严格的证明.可以看看这篇文章 http://ww ...
- CF 2015 ICL, Finals, Div. 1 J. Ceizenpok’s formula [Lucas定理]
http://codeforces.com/gym/100633/problem/J Lucas定理P不是质数裸题 #include <iostream> #include <cst ...
- 【codeforces 779E】Bitwise Formula
[题目链接]:http://codeforces.com/contest/779/problem/E [题意] 给你n个长度为m的二进制数 (有一些是通过位运算操作两个数的形式给出); 然后有一个未知 ...
- Codeforces Problem 778B Bitwise Formula
题目链接:http://codeforces.com/contest/779/problem/E 题意:有n个变量都可以用m位二进制数表示,这n个数的value将以两种格式中的一种给出 1.变量名, ...
- codeforces2015ICL,Finals,Div.1#J Ceizenpok’s formula【扩展lucas】
传送门 [题意]: 求C(n,k)%m,n<=108,k<=n,m<=106 [思路]: 扩展lucas定理+中国剩余定理 #include<cstdio> usi ...
随机推荐
- Java虚拟机之类加载机制
⑴背景 Java虚拟机把Class文件加载到内存中,并对数据进行校验,转换解析,和初始化,最终形成被虚拟机直接使用的Java类型,这就是类加载机制. ⑵Jvm加载Class文件机制原理 类的生命周 ...
- vue小白快速入门
一.vue是什么 Vue 是一套用于构建用户界面的渐进式框架. 压缩后仅有17kb 二.vue环境搭建 你直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量. 但在用 ...
- JavaScript(第二天)【语法,变量】
一.语法构成 区分大小写 ECMAScript中的一切,包括变量.函数名和操作符都是区分大小写的.例如:text和Text表示两种不同的变量. 标识符 所谓标识符,就是指变量.函数.属性的名字,或 ...
- 听翁恺老师mooc笔记(6)--指针运算
指针值加1就是将指针值加上sizeof(指针所指变量的类型) 1+1=2,那么指针加1是加上了1这个数字吗?试一下,在代码中定义了char数组,char也是整数,数组名是ac,ac中有10个元素,0- ...
- 201621123060《JAVA程序设计》第二周学习总结
1.本周学习总结 本周学习了JAVA中的引用类.包装类(学习了一种语法:自动装箱)和数组(遍历数组的新方法foreach循环). 2. 书面作业 1.String-使用Eclipse关联jdk源代码 ...
- 洛谷P2894 [USACO08FEB]酒店Hotel
P2894 [USACO08FEB]酒店Hotel https://www.luogu.org/problem/show?pid=2894 题目描述 The cows are journeying n ...
- MSIL实用指南-一维数组的操作
本篇讲解怎么生成和操作一维数组.各种数组类型创建的步骤是一样的,但是加载和保存步骤有所不同. 一.创建数组所有类型的一维数组创建都是一样的,分三步.1.加载数组长度2.生成指令 Newarr < ...
- HDFS文件读写操作(基础基础超基础)
环境 OS: Ubuntu 16.04 64-Bit JDK: 1.7.0_80 64-Bit Hadoop: 2.6.5 原理 <权威指南>有两张图,下次po上来好好聊一下 实测 读操作 ...
- win-zabbix_agent端配置解析
Zabbix agent 在windows上安装部署 部署windows服务器需要在agent服务器上添加到10.4.200.2的路由 蓝泰服务器需要添加10.0.90.5的网关,联通的机器需要添加到 ...
- SpringCloud的服务注册中心(一)
一.概念和定义 1.服务治理:服务注册与服务发现 服务注册中心,提供服务治理功能,用来实现各个微服务实例的自动注册与发现. 服务注册与发现对于微服务系统来说非常重要.有了服务发现与注册,维护人员就不需 ...