Lucas定理与扩展Lucas
来源:互联网 发布:天津大学网络教学 编辑:程序博客网 时间:2024/06/08 13:46
之前看了乘法逆元(详见除法取模与逆元),发现不能处理不互质的情况,于是去找方法,最后找到了Lucas定理。。。
虽然与期待中的不一样,但是还是非常有用的。
(1)Lucas定理:
若p为素数,则有:
因为a的p进制的最后一位为a%p,所以原公式可以转化为:
这个就是我们常使用的公式。
证明:
我们可以用归纳法证明整个定理。我们有下面的式子成立:
上式左右两边的x的某项
其中左边的
(2)扩展Lucas:
若p不是素数,我们将p分解质因数,将
例如:
当我们需要计算
然后对于方程组:
我们可以求出满足条件的最小的
那么我们有:
但是,我们发现,
下面我们介绍如何计算
计算
我们知道,
后面的部分恰好是
下面是计算
#include<cstdio>#include<algorithm>using namespace std;long long pow(long long a, long long b, long long p) { long long res = 1; while(b) { if(b&1) res = res*a%p; a = a*a%p; b >>= 1; } return res;}long long exgcd(long long a, long long b, long long& x, long long& y) { if(!b) { x = 1; y = 0; return a; } long long res = exgcd(b, a%b, y, x); y -= (a/b)*x; return res;}long long reverse(long long a, long long p) { long long x, y; exgcd(a, p, x, y); return (x % p + p)%p;}long long C(long long n, long long m, long long p) { if(m>n) return 0; long long res = 1, i, a, b; for(i = 1; i <= m; i++) { a = (n+1-i) % p; b = reverse(i%p, p); res = res*a%p*b%p; } return res;}long long Lucas(long long n, long long m, long long p) { if(m == 0) return 1; return Lucas(n/p, m/p, p)*C(n%p, m%p, p) % p;}long long cal(long long n, long long a, long long b, long long p) { if(!n) return 1; long long i, y = n/p, tmp = 1; for(i = 1; i <= p; i++) if(i%a) tmp = tmp*i%p; long long ans = pow(tmp, y, p); for(i = y*p+1; i <= n; i++) if(i%a) ans = ans*i%p; return ans * cal(n/a, a, b, p)%p;}long long multiLucas(long long n, long long m, long long a, long long b, long long p) { long long i, t1, t2, t3, s = 0, tmp; for(i = n; i; i/=a) s += i/a; for(i = m; i; i/=a) s -= i/a; for(i = n-m; i; i/=a) s -= i/a; tmp = pow(a, s, p); t1 = cal(n, a, b, p); t2 = cal(m, a, b, p); t3 = cal(n-m, a, b, p); return tmp*t1%p*reverse(t2, p)%p*reverse(t3, p)%p;}long long exLucas(long long n, long long m, long long p) { long long i, d, c, t, x, y, q[100], a[100], e = 0; for(i = 2; i*i <= p; i++) { if(p % i == 0) { q[++e] = 1; t = 0; while(p%i==0) { p /= i; q[e] *= i; t++; } if(q[e] == i) a[e] = Lucas(n, m, q[e]); else a[e] = multiLucas(n, m, i, t, q[e]); } } if(p > 1) { q[++e] = p; a[e] = Lucas(n, m, p); } for(i = 2; i <= e; i++) { d = exgcd(q[1], q[i], x, y); c = a[i]-a[1]; if(c%d) exit(-1); t = q[i]/d; x = (c/d*x%t+t)%t; a[1] = q[1]*x+a[1]; q[1] = q[1]*q[i]/d; } return a[1];}int main() { long long n, m, p; scanf("%lld%lld%lld", &n, &m, &p); printf("%lld\n", exLucas(n, m, p)); return 0;}
1 0
- Lucas定理与扩展Lucas
- lucas定理及扩展lucas定理
- hdu3439 Lucas定理扩展
- 扩展Lucas定理
- BZOJ2142 礼物 [扩展lucas定理]
- Lucas 定理
- Lucas 定理
- lucas定理
- Lucas定理
- Lucas 定理
- Lucas 定理
- Lucas 定理
- Lucas 定理
- Lucas定理
- lucas定理
- lucas定理
- Lucas定理
- Lucas定理
- C++primer plus 第11-12章笔记
- UVA - 572 Oil Deposits
- 通过TortoiseGit上传项目到GitHub
- 大数四则运算的C++实现
- 蓝鸥 8.10
- Lucas定理与扩展Lucas
- 应用里的用户头像是怎样更改的?
- leetcode(368):Largest Divisible Subset
- mashen8.10--作业
- a 标签中调用js的几种方法
- UVA - 657 The die is cast
- PAT 1010. Radix
- C/C++的class和struct的区别
- 在一个排序数组中,输出给定数字出现的次数