ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

同余系全家桶

2022-08-20 19:02:36  阅读:127  来源: 互联网

标签:lfloor return dbinom bmod 全家 同余系 ll equiv


一.逆元

如果一个线性同余方程 \(ax \equiv 1 \pmod b\),则称 \(x\) 为 \(a \bmod b\) 的逆元,记为 \(a^{-1}\)。

使用方法

对于 \(\frac{a}{b} \bmod p\),求出 \(b \bmod p\) 的逆元,与 \(a\) 相乘并 \(\bmod p\) 得到结果。

优势:避免了分数的精度问题。

求逆元

exgcd 法

求解 \(ax \equiv 1 \pmod b\),可以变形为求解 \(ax+by =1\),使用 exgcd。

code:

点击查看代码
void exgcd(ll a, ll b, ll &x, ll &y) {
	if(!b){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
int main() {
	ll x, y;
	cin>>x>>y>>p;
	exgcd(a, p, x, y);
	x=(x % p + p) % p;
	cout<<x;
	return 0;
}

快速幂法

前置知识:费马小定理。

因为 \(ax \equiv 1 \pmod b\)

所以有 \(ax \equiv a^{b-1} \pmod b\)

得 \(x \equiv a^{p-2}\),用快速幂求解。

code:

见 Lucas 代码。

二.CRT

先咕着。

三.Lucas 定理

Lucas 定理是用来求这个东西的:

\[\dbinom{n}{m} \bmod p \]

其中 \(p\) 为较小质数。

其结论为:

\[\dbinom{n}{m} \bmod p = \dbinom{\left\lfloor n/p \right\rfloor}{\left\lfloor m/p \right\rfloor} \cdot \dbinom{n\bmod p}{m\bmod p} \bmod p \]

因为 \(p\) 值较小,\(\binom{n\bmod p}{m\bmod p}\) 可以直接预处理 \(O(1)\) 求解。而 \(\binom{\left\lfloor n/p \right\rfloor}{\left\lfloor m/p \right\rfloor}\) 可以继续用 Lucas 定理分解递归求解。

证明

首先根据定义可知:

\[\dbinom{p}{n} \bmod p=\dfrac{p!}{n! \cdot (n-p)!} \bmod p \]

可以找到性质:仅当 \(n=0 \vee n=p\) 时,该式结果为 \(1\),否则为 \(0\)。

据此扩展可得:

\[\begin{align} (a+b)^p &= \sum_{n=0}^p \binom pn a^n b^{p-n}\\&\equiv \sum_{n=0}^p [n=0\vee n=p] a^n b^{p-n}\\ &\equiv (a^p +b^p) \bmod p \end{align} \]

最后将其推广到二项式情况,将 \(p\) 提进来即可。

也可以参考lhx大佬的另类证明

板子传送门

code:

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
ll t,n,m,p;
ll jie[100005]={1};
ll ksm(ll y,ll z,ll p){
    y%=p;
	ll ans=1;
    for(int i=z;i;i>>=1,y=y*y%p){
    	if(i&1){
    		ans=ans*y%p;
		}
	}
    return ans;
}
ll C(ll n,ll m){
	if(m>n) return 0;
	return ((jie[n]*ksm(jie[m],p-2,p))%p*ksm(jie[n-m],p-2,p)%p);
}
ll lucas(ll n,ll m){
	if(m==0) return 1;
	return lucas(n/p,m/p)*C(n%p,m%p)%p;
}
int main(){
	cin>>t;
	while(t--){
		cin>>n>>m>>p;
		jie[0]=1;
		for(int i=1;i<=p;i++){
			jie[i]=jie[i-1]*i%p;
		}	
		cout<<lucas(n+m,n)<<endl;
	}
	return 0;
}

我才不会告诉你这东西其实只有结论需要记略略略

例题: [SHOI2015]超能粒子炮·改

题意:求

\[\sum_{i=0}^k\dbinom{n}{i} \bmod p \]

且\(p=2333\)

思路:

首先用 Lucas 变形可得:

\[\sum_{i=0}^k \cdot \dbinom{\left\lfloor n/p \right\rfloor}{\left\lfloor i/p \right\rfloor} \cdot \dbinom{n\bmod p}{i\bmod p} \bmod p \]

我草,剩下的不会了。

四.扩展 Lucas 定理(exLucas)

恶心东西。不想写。

标签:lfloor,return,dbinom,bmod,全家,同余系,ll,equiv
来源: https://www.cnblogs.com/victoryang-not-found/p/16603501.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有