二项式定理和杨辉三角

发布时间 2023-07-11 20:26:01作者: 天雷小兔

 

杨辉三角

解法1:dfs

使用记忆化搜索,提升dfs效率

代码:

int dfs(int n,int m){
	if(!m)return c[n][m]=1;
	if(m==1)return c[n][m]=n;
	if(c[n][m])return c[n][m];
	if(n-m<m)m=n-m;
	return c[n][m]=(dfs(n-1,m)+dfs(n-1,m-1))%mod;
}

  

解法2:递推

时间复杂度O(n^2),如果n较大,建议使用逆运算的方法

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4+39+7;
ll a[N][N],n,m;
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)a[i][1]=a[i][i]=1;
	for(int i=2;i<=n;i++){
		for(int j=2;j<=n;j++){
			a[i][j]=a[i-1][j]+a[i-1][j-1];
		}
	}
	cout<<a[n][m];
	return 0;
}

  

解法3:逆运算

速度最快,但是涉及到阶乘,所以需要取模

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+1,mod = 1e4+7;
short int fac[N],inv[N];
int quickPow(int a,int n){
	int ans=1;
	a%=mod;
	while(n){
		if(n&1)ans=(ans*a)%mod;
		a=(a*a)%mod;
		n>>=1;
	}
	return ans;
}
int c(int n,int m){
	return (fac[n]*inv[m]%mod*inv[n-m]%mod)%mod;
}
int main(){
	int a,b,n,m,k;cin>>a>>b>>k>>n>>m;
	fac[0]=1;
	for(int i=1;i<=n+m;i++){
		fac[i]=(fac[i-1]*i)%mod;
		inv[i]=quickPow(fac[i],mod-2);
	}
	cout<<(quickPow(a,n)%mod*quickPow(b,m)%mod*c(k,n)%mod);
	return 0;
}

  

杨辉三角使用了组合数的第2个性质:C(n,r)=C(n-1,r)+C(n-1,r-1)

杨辉三角的主要应用是二项式定理与dp基础模型

 

二项式定理

二项式定理原式:(a+b)n=sum(C(n,r)*ar*bn-r)=sum(C(n,r)*br*an-r)

下面给出一道例题:P1313 [NOIP2011 提高组] 计算系数

根据二项式定理,直接求得答案

解法1:dfs

又慢又耗空间

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+39+7,mod = 1e4+7;
int c[N][N];
int quickPow(int a,int n){
	int ans=1;
	a%=mod;
	while(n){
		if(n&1)ans=(ans*a)%mod;
		a=(a*a)%mod;
		n>>=1;
	}
	return ans;
}
int dfs(int n,int m){
	if(!m)return c[n][m]=1;
	if(m==1)return c[n][m]=n;
	if(c[n][m])return c[n][m];
	if(n-m<m)m=n-m;
	return c[n][m]=(dfs(n-1,m)+dfs(n-1,m-1))%mod;
}
int main(){
	int a,b,k,n,m;cin>>a>>b>>k>>n>>m;
	c[1][0]=c[1][1]=1;
	int ans=1;
	ans*=(quickPow(a,n)*quickPow(b,m))%mod;
	ans*=dfs(k,n)%mod;
	cout<<ans%mod;
	return 0;
}

  

解法2:逆运算

最快且最省空间

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e3+39+7,mod = 1e4+7;
int fac[N],inv[N];
int quickPow(int a,int n){
	int ans=1;
	a%=mod;
	while(n){
		if(n&1)ans=(ans*a)%mod;
		a=(a*a)%mod;
		n>>=1;
	}
	return ans;
}
int c(int n,int m){
	return (fac[n]*inv[m]%mod*inv[n-m]%mod)%mod;
}
int main(){
	int a,b,n,m,k;cin>>a>>b>>k>>n>>m;
	fac[0]=1;
	for(int i=1;i<=n+m;i++){
		fac[i]=(fac[i-1]*i)%mod;
		inv[i]=quickPow(fac[i],mod-2);
	}
	cout<<(quickPow(a,n)%mod*quickPow(b,m)%mod*c(k,n)%mod);
	return 0;
}