CRT中国剩余定理 & Lucas卢卡斯定理
数论_CRT(中国剩余定理)& Lucas (卢卡斯定理)
前言
又是一脸懵逼的一天。
正文
按照道理来说,我们应该先做一个介绍。
中国剩余定理
中国剩余定理,Chinese Remainder Theorem,又称孙子定理,给出了一元线性同余方程组的有解判定条件,并用构造法给出了通解的具体形式。
现在有方程组:中国剩余定理指出:


扩展中国剩余定理
在一般情况下,要求任两个数互质这个条件太苛刻了,CRT派不上用场,我们需要一个更具普遍性的结论,这就是EX-CRT。虽然是称为EX-CRT,但这个定理并没有直接用到CRT的结论。

typedef long long ll;
const int maxn = 111;
// m为模数组,a为余数数组,0~n-1
ll m[maxn], a[maxn];
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1; y = 0;
return a;
}
ll ans = exgcd(b, a % b, y, x);
y -= a / b * x;
return ans;
}
ll excrt() {
ll lcm = m[0], last_a = a[0];
for(int i = 1; i < n; i++) {
ll lcm_a = ((a[i] - last_a) % m[i] + m[i]) % m[i];
ll k = lcm, x, y;
ll gcd = exgcd(lcm, m[i], x, y);
ll mod = m[i] / gcd;
x = (x * lcm_a / gcd % mod + mod) % mod;
lcm = lcm / gcd * m[i], last_a = (last_a + k * x) % lcm;
}
return (last_a % lcm + lcm) % lcm;
}
卢卡斯定理
卢卡斯定理是关于组合数和同余的定理,它表明当p为素数时:

其中,即为的进制展开中对应次数为的系数
因为当m>n时,二项式系数为0,那么二项式系数即组合数能被p整除等价于在p进制下,存在某一位m的数值大于对应的n的数值。
基于母函数可以简单证明这个定理。

可以用除法和取模方便的在循环中求出各个系数,代码如下:
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 100;
void init() {
F[0] = 1;
for(int i = 2; i < maxn; i++)
F[i] = i * F[i - 1] % mod;
}
ll qpow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
b >>= 1; a = a * a % mod;
}
return ans;
}
ll lucas(ll N, ll M) {
ll ans = 1;
while(N & M) {
ll n = N % mod, m = M % mod;
if(n < m) return 0;
ans = ans * F[a] % mod * qpow(F[m] * F[n - m] % mod, mod - 2) % mod;
N /= p; M /= p;
}
return ans;
}
扩展卢卡斯定理
卢卡斯定理同样不能处理模数不是素数的情况,这时便需要扩展卢卡斯定理。我们一步步分析如何求解模数不是素数的组合数问题。
首先,我们要解决的问题是求,其中不一定是素数。对于非素数,我们首先会联想到质因分解后结合解决问题。假设分解得到个质数,质数对应的个数为,对质因分解有。显然对,,,假设对,我们求出了,那么我们可以得到同余方程组::这时我们便可以套用解决问题,那么问题便转化为如何求解。
现在我们要求的是,其中是素数。又,显然需要求出和关于模的逆元,但考虑到这些项中可能包含(含有则不互质,逆元不存在),所以需要先提取,得到:,这里的阶乘是指提取之后的结果。这时就可以计算和关于的逆元了。这里,为了形式的统一,同时提取了中的。那么,问题又转化为了如何求。
目标:计算,为质数。上一步中提到,我们需要先提取。提取结果为:。第一部分很好理解,对于每一个的倍数,都可以提取出一个,一共有个;第二部分为的倍数被提取之后余下的,是一个阶乘的形式。显然在中,对于的幂,的个数不止个,也就是说第二部分仍然需要提取,这一部分可以递归解决。第三部分是剔除了的倍数之后余下的。对,,都有对,这也就是说,第三部分其实是存在循环节的,一共循环了次。除去循环节的余项长度在之内,直接累乘即可。
完整代码如下:
typedef long long ll;
const int N = 1e6 + 100;
ll n, m, p;
ll qpow(ll a, ll b, ll mod) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
b >>= 1; a = a * a % mod;
}
return ans;
}
ll fac(ll n, ll p, ll pk) {
if (!n) return 1;
ll ans = 1;
for (int i = 1; i < pk; i++)
if (i % p) ans = ans * i % pk;
ans = qpow(ans, n / pk, pk);
int npk = n % pk;
for (int i = 1; i <= npk; i++)
if (i % p) ans = ans * i % pk;
return ans * fac(n / p, p, pk) % pk;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1; y = 0;
return a;
}
ll ans = exgcd(b, a % b, y, x);
y -= a / b * x;
return ans;
}
ll inv(ll a, ll p) {
return qpow(a, p - 2, p);
}
ll C(ll n, ll m, ll p, ll pk) {
if (n < m) return 0;
ll fn = fac(n, p, pk),
fm = fac(m, p, pk),
fn_m = fac(n - m, p, pk),
cnt = 0;
for (ll i = n; i; i /= p)
cnt += i / p;
for (ll i = m; i; i /= p)
cnt -= i / p;
for (ll i = n - m; i; i /= p)
cnt -= i / p;
return fn * inv(fm * fn_m % pk, pk) % pk * qpow(p, cnt, pk) % pk;
}
ll a[N], mod[N]; // a[]是通过卢卡斯分解出来的组合数值,m[]是对应的模数
int cnt; // 质因数的种数
ll CRT() {
ll M = 1, ans = 0;
for (int i = 0; i < cnt; i++)
M *= mod[i];
for (int i = 0; i < cnt; i++)
ans = (ans + a[i] * (M / mod[i]) % M * inv(M / mod[i], mod[i]) % M) % M;
return ans;
}
ll exlucas(ll n, ll m, ll p) {
ll sqrtp = sqrt(p + 0.5);
for (int i = 2; p > 1 && i <= sqrtp; i++) {
ll pk = 1;
while (p % i == 0)
p /= i, pk *= i;
if (pk > 1)
a[cnt] = C(n, m, i, pk), mod[cnt++] = pk;
}
if (p > 1)
a[cnt] = C(n, m, p, p), mod[cnt++] = p;
return CRT();
}
题目
其实这篇博客到这里几乎就可以没了,因为我。。。爆0了
难啊。。。
A题
Biorhythms HDU-1370
题意
一个人有三个值(不知道是啥),然后每个值每到一个周期就会到达顶峰,求从d天开始,他三个值都到达顶峰是第几天。
思路
然而,三个周期都是质数,显然用的是中国剩余定理(CRT)
抽象一点来说,就是给你三个同余方程。
代码
1 #include <iostream>
2 #include <cstdio>
3 #include <algorithm>
4 #include <cmath>
5 #include <cstring>
6 using namespace std;
7 typedef long long ll;
8 ll exgcd(ll a, ll b, ll &x, ll &y)
9 {
10 if(!b)
11 {
12 x = 1;
13 y = 0 * 100;
14 return a;
15 }
16 ll d = exgcd(b, a % b, x, y);
17 ll t = x;
18 x = y;
19 y = t - a / b * y;
20
21 return d;
22 }
23
24 ll inv(ll a,ll n)
25 {
26 ll y, d, x, fre, pf, qw;
27 /*cnt't*/
28 fre = pf = qw = 1;
29 fre++, pf++, qw++;
30 /*can't*/
31 d = exgcd(a,n,x,y);
32 return d == 1 ? (x + n) % n:-1;
33 }
34
35 ll CN(ll leo, ll *a, ll *m)
36 {
37 ll M = 1, ret = 0;
38 for(ll i = 0; i < leo; i ++)
39 M *= m[i];
40
41 for(ll i = 0; i < leo; i ++)
42 {
43 ll w = M / m[i];
44 ret = (ret + w * inv(w, m[i]) * a[i]) % M;
45 }
46 return (ret + M) % M;
47 }
48 int main()
49 {
50 ll t = 1, d;
51 ll a[10],m[10];
52 m[0] = 23;
53 m[1] = 28;
54 m[2] = 33;
55 /*GN*/
56 ll tea;
57 scanf("%lld", &tea);
58 while(true)
59 {
60 scanf("%lld%lld%lld%lld", &a[0], &a[1], &a[2], &d);
61
62 if(a[0] == -1 && a[1] == -1 && a[2] == -1 && d == -1)
63 break;
64 ll ans = CN(3, a, m);
65 if(ans <= d)
66 ans += 21252;
67 ans -= d;
68
69 printf("Case %lld: the next triple peak occurs in %lld days.\n", t, ans);
70 t++;
71 }
72 return 0;
73 }
B题
Big Coefficients HDU-3929
题意
略
思路
显然是用卢卡斯,但我不知道为哈
未完待续
CRT中国剩余定理 & Lucas卢卡斯定理的更多相关文章
- [SDOI2010] 古代猪文 (快速幂+中国剩余定理+欧拉定理+卢卡斯定理) 解题报告
题目链接:https://www.luogu.org/problemnew/show/P2480 题目背景 “在那山的那边海的那边有一群小肥猪.他们活泼又聪明,他们调皮又灵敏.他们自由自在生活在那绿色 ...
- HDU 5446 中国剩余定理+lucas
Unknown Treasure Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- 【bzoj1951】: [Sdoi2010]古代猪文 数论-中国剩余定理-Lucas定理
[bzoj1951]: [Sdoi2010]古代猪文 因为999911659是个素数 欧拉定理得 然后指数上中国剩余定理 然后分别lucas定理就好了 注意G==P的时候的特判 /* http://w ...
- 中国剩余定理&Lucas定理&按位与——hdu 5446
链接: hdu 5446 http://acm.hdu.edu.cn/showproblem.php?pid=5446 题意: 给你三个数$n, m, k$ 第二行是$k$个数,$p_1,p_2,p_ ...
- hdu 5446 Unknown Treasure 中国剩余定理+lucas
题目链接 求C(n, m)%p的值, n, m<=1e18, p = p1*p2*...pk. pi是质数. 先求出C(n, m)%pi的值, 然后这就是一个同余的式子. 用中国剩余定理求解. ...
- 51 Nod 1079 中国剩余定理(孙子定理)NOTE:互质情况
1079 中国剩余定理 一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K.例如,K % 2 = 1, K % 3 = 2, K % 5 = 3.符合条件的最小的K = 23. 收起 ...
- Lucas 卢卡斯定理
Lucas: 卢卡斯定理说白了只有一条性质 $$ C^n_m \equiv C^{n/p}_{m/p} \times C^{n \bmod p}_{m \bmod p} \ (mod \ \ p) $ ...
- Lucas(卢卡斯)定理模板&&例题解析([SHOI2015]超能粒子炮·改)
Lucas定理 先上结论: 当p为素数: \(\binom{ N }{M} \equiv \binom{ N/p }{M/p}*\binom{ N mod p }{M mod p} (mod p)\) ...
- Lucas卢卡斯定理
当$p$为素数时 $$C_n^m\equiv C_{n/p}^{m/p}*C_{n\%p}^{m\%p}(mod\ p)$$ 设$n=s*p+q,m\equiv t*p+r(q,r<=p)$ 我 ...
随机推荐
- js中的闭包理解
闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的 ...
- 巨杉Tech | 微服务趋势下的数据库设计与应用简析
周五(7月12日)巨杉数据库参与了由得到App主办八里庄技术沙龙活动,分享主题是关于分布式数据库架构与实战. 以下就是根据巨杉数据库现场分享的内容进行的分享实录整理. 巨杉数据库简介 巨杉,专注新一代 ...
- jdk8-》stream⾥的map和filter函数使⽤
map函数 将流中的每⼀个元素 T(入参) 映射为 R(返回值)(类似类型转换) 类似遍历集合,对集合的每个对象做处理.场景:转换对象,如javaweb开发中集合⾥⾯的DO对象转换为DTO对象 ...
- hashlib加密模块_python
一.hashlib模块 1.功能 主要用于字符串加密 2.常用方法 md5()/sha1():创建一个md5或者sha1加密模式的hash对象update(arg):用字符串参数来更新hash对象,如 ...
- whindows下存储文件技巧
文件名中不能有\/:*?"<>|这些符号 因为python存储的时候一直失败……就很糟心 下划线是可以的 希望对大家有所帮助 以上
- Linux零碎002
1.if else就近原则: 2.指针位数与机器地址总线宽度一致: 3.数组即常量指针,用法和指针类似,在操作指针时:p与&p[0]含义一样: 4.编译器按照内存递减的方式来分配变量.
- 用户注册(php)login(非美化)
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- zabbix4.2配置监控nginx服务
1.监控原理 通过status模块监控(--with-http_stub_status_module) 2.修改nginx配置(/etc/nginx/conf.d/default.conf) 在被监 ...
- php自带的密码哈希
常用的MD5.SHA1.SHA256哈希算法,是面向快速.高效进行哈希处理而设计的.随着技术进步和计算机硬件的提升,如今强大的计算机很容易破解这种算法.也就是说,不要用MD5.SHA1.SHA256这 ...
- IDEA与Tomcat相关配置
idea会为每一个Tomcat部署的项目,独立建一份配置文件. 配置文件所在位置 怎么部署的(查看虚拟目录)使用的第三种部署方式 部署项目存放的路径 项目目录和Tomcat部署目录 Tomcat真正访 ...