acw数学知识(下)

数论基础知识

10. 高斯消元

10.1 步骤

枚举每一列c
1.找到该列绝对值最大的一行
2.换到最上面
3.将该行第一个数变成1
4.将下面所有行的第c列消成0

const int N=110;
const double eps=1e-6;
int n;
double a[N][N];

int gauss()
{
	int c,r;
	for(c=0,r=0;c<n;c++)
	{
		int t=r;
		for(int i=r;i<n;i++)
			if(fabs(a[i][c])>fabs(a[t][c]))
				t=i;
		if(fabs(a[t][c])<eps) continue;
		for(int i=c;i<=n;i++) swap(a[t][i],a[r][i]);
		for(int i=n;i>=c;i--) a[r][i]/=a[r][c];
		for(int i=r+1;i<n;i++)
			if(fabs(a[i][c])>eps)
				for(int j=n;j>=c;j--)
					a[i][j]-=a[r][j]*a[i][c];
		r++;
	}
	if(r<n) 
	{
		for(int i=r;i<n;i++)
			if(fabs(a[i][n])>eps) 
				return 2;//无解
		return 1;//无穷组解
	}
	for(int i=n-1;i>=0;i--)
		for(int j=i+1;j<n;j++)
			a[i][n]-=a[i][j]*a[j][n];
	return 0;//一组解
}

11. 组合数

11.1 递归法

1<=b<=a<=20001<=b<=a<=20001<=b<=a<=2000

for(int i=0;i<N;i++)
	for(int j=0;j<=i;j++)
		if(!j) c[i][j]=1;
		else c[i][j]=c[i-1][j-1]+c[i-1][j];
11.2 通过预处理逆元的方式

1<=b<=a<=1e51<=b<=a<=1e51<=b<=a<=1e5
∵\because a!b!\frac{a!}{b!}b!a! (mod p)(mod\ p)(mod p) ≠≠= a! (mod p)b! (mod p)\frac{a!\ (mod\ p)}{b!\ (mod\ p)}b! (mod p)a! (mod p)
所以,可以转化为:a!∗d!a!*d!a!d! (mod p)(mod\ p)(mod p)
其中,did_idibib_ibippp 的逆元,等于bip−2b_i^{p-2}bip2

int fact[N],infact[N];
int qmi(int a,int k,int p)
{
	int res=1;
	while(k)
	{
		if(k&1) res=(ll)res*a%p;
		a=(ll)a*a%p;
		k>>=1;
	}
	return res;
}
fact[0]=infact[0]=1;
for(int i=1;i<N;i++)
{
	fact[i]=(ll)fact[i-1]*i%mod;
	infact[i]=(ll)infact[i-1]*qmi(i,mod-2,mod)%mod;//逆元
}
11.3 卢卡斯定理

1<=b<=a<=1e18,1<=p<=1e51<=b<=a<=1e18,1<=p<=1e51<=b<=a<=1e18,1<=p<=1e5

11.3.1定理

PPP为素数,a,b∈ N∗a,b\in\ N^*a,b N,并且
a=ak∗pk+ak−1∗pk−1+⋅⋅⋅+a1∗p+a0b=bk∗pk+bk−1∗pk−1+⋅⋅⋅+b1∗p+b0a=a_k*p^k+a_{k-1}*p^{k-1}+···+a_1*p+a_0\\b=b_k*p^k+b_{k-1}*p^{k-1}+···+b_1*p+b_0a=akpk+ak1pk1+⋅⋅⋅+a1p+a0b=bkpk+bk1pk1+⋅⋅⋅+b1p+b0
这里0<=ai,bi<=p−10<=a_i,b_i<=p-10<=ai,bi<=p1都是整数,i=0,1,2,⋅⋅⋅,ki=0,1,2,···,ki=0,1,2,⋅⋅⋅,k,则有
Cab≡Cakbk∗Cak−1bk−1∗⋅⋅⋅∗Ca0b0 (mod P)C_a^b≡C_{a_k}^{b_k}*C_{a_{k-1}}^{b_{k-1} }*···*C_{a_0}^{b_0}\ (mod\ P)CabCakbkCak1bk1⋅⋅⋅Ca0b0 (mod P)

11.3.2证明

(1+x)p=Cp0∗1+Cp1∗x+Cp2∗x2+⋅⋅⋅+Cpp∗xp(1+x)^p=C_p^0*1+C_p^1*x+C_p^2*x^2+···+C_p^p*x^p(1+x)p=Cp01+Cp1x+Cp2x2+⋅⋅⋅+Cppxp
因为ppp是素数
所以Cpi∗xiC_p^i*x_iCpixi没有<p<p<p的质因子,可知Cpi∗xi≡0 (mod p)C_p^i*x_i\equiv0\ (mod\ p)Cpixi0 (mod p)
得到(1+x)p≡1+xp (mod p)(1+x)^p≡1+x^p\ (mod\ p)(1+x)p1+xp (mod p)
利用上述结果,可知
(1+x)a=(1+x)a0∗((1+x)p)a1∗⋅⋅⋅∗((1+x)pk)ak                           ≡(1+x)a0∗((1+xp)a1∗⋅⋅⋅∗((1+xpk)ak (mod p)(1+x)^a=(1+x)^{a_0}*((1+x)^p)^{a_1}*···*((1+x)^{p_k})^{a_k}\\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \equiv(1+x)^{a_0}*((1+x^p)^{a_1}*···*((1+x^{p_k})^{a_k}\ (mod\ p)(1+x)a=(1+x)a0((1+x)p)a1⋅⋅⋅((1+x)pk)ak                           (1+x)a0((1+xp)a1⋅⋅⋅((1+xpk)ak (mod p)
左右式中,xbx^bxb的系数相等可得
Cab≡Cakbk∗Cak−1bk−1∗⋅⋅⋅∗Ca0b0 (mod p)C_a^b\equiv C_{a_{k}}^{b_{k}}*C_{a_{k-1}}^{b_{k-1}}*···*C_{a_{0}}^{b_{0}}\ (mod\ p)CabCakbkCak1bk1⋅⋅⋅Ca0b0 (mod p)

11.3.3代码
typedef long long ll;
int a,b,p;
int qmi(int a,int k)
{
	int res=1;
	while(k)
	{
		if(k&1) res=(ll)res*a%p;
		a=(ll)a*a%p;
		k>>=1;
	}
	return res;
}
int C(int a,int b)
{
	int res=1;
	for(int i=1,j=a;i<=b;i++,j--)
	{
		res=(ll)res*j%p;
		res=(ll)res*qmi(i,p-2)%p;
	}
	return res;
}
int lucas(ll a,ll b)
{
	if(a<p&&b<p) return C(a,b);
	return (ll)C(a%p,b%p)*lucas(a/p,b/p)%p;
}
11.4 分解质因数法求组合数
11.4.1内容

Cab=a!b!∗(a−b)!C_a^b=\frac{a!}{b!*(a-b)!}Cab=b!(ab)!a!
分解质因数得
a!=p1α1∗p2α2∗⋅⋅⋅∗pkαka!=p_1^{\alpha_1}*p_2^{\alpha_2}*···*p_k^{\alpha_k}a!=p1α1p2α2⋅⋅⋅pkαk
b!=p1β1∗p2β2∗⋅⋅⋅∗pkβkb!=p_1^{\beta_1}*p_2^{\beta_2}*···*p_k^{\beta_k}b!=p1β1p2β2⋅⋅⋅pkβk
(a−b)!=p1γ1∗p2γ2∗⋅⋅⋅∗pkγk(a-b)!=p_1^{\gamma_1}*p_2^{\gamma_2}*···*p_k^{\gamma_k}(ab)!=p1γ1p2γ2⋅⋅⋅pkγk
其中,
α=⌊ap⌋+⌊ap2⌋+⌊ap3⌋+⋅⋅⋅\alpha=\lfloor \frac{a}{p} \rfloor+\lfloor \frac{a}{p^2} \rfloor+\lfloor \frac{a}{p^3} \rfloor+···α=pa+p2a+p3a+⋅⋅⋅
ppp的倍数的个数+p2p^2p2的倍数的个数+···
那么,对于CabC_a^bCab的某个质因数pip_ipi,指数为αi−βi−γi\alpha_i-\beta_i-\gamma_iαiβiγi

11.4.2 代码
const int N=5010;
int sum[N],primes[N],cnt;
bool st[N];
void get_primes(int n)
{
	for(int i=2;i<=n;i++)
	{
		if(!st[i]) primes[cnt++]=i;
		for(int j=0;primes[j]<=n/i;j++)
		{
			st[primes[j]*i]=true;
			if(i%primes[j]==0) break;
		}
	}
}
int get(int n,int p)//获取指数
{
	int res=0;
	while(n)
	{
		res+=n/p;
		n/=p;
	}
	return res;
}
vector<int> mul(vector<int> a,int b)//高精度乘法
{
	vector<int> c;
	int t=0;
	for(int i=0;i<(int)a.size();i++)
	{
		t+=a[i]*b;
		c.push_back(t%10);
		t/=10;
	}
	while(t)
	{
		c.push_back(t%10);
		t/=10;
	}
	return c;
}
int main()
{
	int a,b;
	cin>>a>>b;
	get_primes(a);
	for(int i=0;i<cnt;i++)
	{
		int p=primes[i];
		sum[i]=get(a,p)-get(b,p)-get(a-b,p);
	}
	vector<int> res;
	res.push_back(1);
	for(int i=0;i<cnt;i++)
		for(int j=0;j<sum[i];j++)
			res=mul(res,primes[i]);
	for(int i=res.size()-1;i>=0;i--)
		printf("%d",res[i]);
}
11.5 卡特兰数

卡特兰数是组合数学中一个常出现于各种计数问题中的数列。其前几项为(从第0项开始):1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …

11.5.1几何意义

给定nnn000nnn111,它们将按照某种顺序排成长度为2n2n2n的序列,求它们能排成的所有序列中,能够满足任意前缀序列中0的个数不少于1的个数的序列有多少。
转化到二维坐标中,就是求从原点(0,0)(0,0)(0,0)出发到(n,n)(n,n)(n,n)满足已走路径始终是右移步数多于上移步数的方案数。即路线不超过直线y=xy=xy=x上部。

11.5.2推导

总方案数:从原点(0,0)(0,0)(0,0)出发到(n,n)(n,n)(n,n),需要右移nnn步,上移nnn步才能到达终点,方案数为C2nnC_{2n}^nC2nn步。
触碰红线:即从原点(0,0)(0,0)(0,0)出发到(n−1,n+1)(n-1,n+1)(n1,n+1),方案数Cn−12nC_{n-1}^{2n}Cn12n
那么合法方案数:C2nn−Cn−12nC_{2n}^n-C_{n-1}^{2n}C2nnCn12n
化简后,Catalann=1n+1∗C2nnCatalan_n=\frac{1}{n+1}*C_{2n}^nCatalann=n+11C2nn
在这里插入图片描述

12. 容斥原理
12.1基本思想

先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。
nnn个元素,奇数个加,偶数个减,一共2n−12^n-12n1
∣S1∪ S2∪ S3∣=∣S1∣+∣S2∣+∣S3∣−∣S1∩ S2∣−∣S1∩ S3∣−∣S2∩ S3∣+∣S1∩ S2∩ S3∣|S_1\cup\ S_2\cup\ S_3|=|S_1|+|S_2|+|S_3|-|S_1\cap\ S_2|-|S_1\cap\ S_3|-|S_2\cap\ S_3|+|S_1\cap\ S_2\cap\ S_3|S1 S2 S3=S1+S2+S3S1 S2S1 S3S2 S3+S1 S2 S3
Cn1−Cn2+Cn3−⋅⋅⋅+(−1)k−1Ckk=1C_n^1-C_n^2+C_n^3-···+(-1)^{k-1}C_k^k=1Cn1Cn2+Cn3⋅⋅⋅+(1)k1Ckk=1

13. 博弈论

先手必胜状态:可以走到某一个必败状态
先手必败状态:走不到任何一个必败状态

13.1Nim游戏
13.1.1 规则

有n堆石子,两个玩家轮流拿石子,每次从任意一堆中拿走任意数量的石子,不能不拿,拿到最后一个石子的玩家获胜。

13.1.2 结论

a1∧a2∧⋅⋅⋅∧an=0a_1\wedge a_2\wedge···\wedge a_n=0a1a2⋅⋅⋅an=0 先手必败
a1∧a2∧⋅⋅⋅∧an≠0a_1\wedge a_2\wedge···\wedge a_n \neq0a1a2⋅⋅⋅an=0 先手必胜

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值