问题一:计算 C(n,m)
1、定义式
long long C(long long n,long long m)
{
long long ans=1;
for(long long i=1;i<=n;i++)
{
ans*=i;
}
for(long long i=1;i<=m;i++)
{
ans/=i;
}
for(long long i=1;i<=n-m;i++)
{
ans/=i;
}
return ans;
}
2、公式
//1、C(n,m)=C(n-1,m)+C(n-1,m-1)
long long C(long long n,long long m)
{
if(m==0||m==n) return 1;
return C(n-1,m)+C(n-1,m-1);
}
//2、记录型递归!!!!!
long long ans[67][67]={0};
long long C(long long n,long long m)
{
if(m==0||m==n) return 1;
if(ans[n][m]!=0) return ans[n][m];
return ans[n][m]=C(n-1,m)+C(n-1,m-1);
}
3、边乘边除----定义式的变形
long long C(long long n,long long m)
{
long long ans=1;
for(long long i=1;i<=m;i++)
{
ans=ans*(n-m+i)/i;
}
return ans;
}
问题二:计算C(n,m)%p
1、递推公式
//①、递归
int ans[1010][1010]={0};
int C(int n,int m,int p)
{
if(n==m||m==0) return 1;
if(ans[n][m]!=0) return ans[n][m];
return ans[n][m]=(C(n-1,m)+C(n-1,m-1))%p;
}
//②、递推
void calC()
{
for(int i=0;i<=n;i++)
{
ans[i][0]=ans[i][i]=1;
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i/2;i++)
{
ans[i][j]=(ans[i-1][j]+ans[i-1][j-1])%p;
ans[i][i-j]=ans[i][j];
}
}
}
2、根据定义式计算
/*
int cal(int n,int p)
{
int ans=0;
while(n)
{
ans+=n/p;
n/=p;
}
return ans;
}
*/
/*
int binaryPow(int a,int b,int m)
{
if(b==0) return 1;
if(b%2==1) return a*binaryPow(a,b-1,m)%m;
else
{
int mul=binaryPow(a,b/2,m);
return mul*mul%m;
}
}
*/
int prime[maxn];
int C(int n,int m,int p)
{
int ans=1;
for(int i=0;prime[i]<=n;i++)
{
int c=cal(n,prime[i])-cal(m,prime[i])-cal((n-m),prime[i]);
ans=ans*binaryPow(prime[i],c,p)%p;
}
return ans;
}
3、通过定义式的变形
//①、m<p,p为素数
int C(int n,int m,int p)
{
int ans=1;
for(int i=1;i<=m;i++)
{
ans=ans*(n-m+i)%p;
ans=ans*inverse(i,p)%p;
}
return ans;
}
//②、m任意,p为素数
int C(int n,int m,int p)
{
int ans=1;
int numP=0; //统计分子中的p比分母中的p多几个
for(int i=1;i<=m;i++)
{
int temp=n-m+i;
while(temp%p==0)
{
numP++;
temp/=p;
}
ans=ans*temp%p;
temp=i;
while(temp%p==0)
{
numP++;
temp/=p;
}
ans=ans*inverse(temp,p)%p;
}
if(numP>0) return 0;
else return ans;
}
4、Lucas定理
int p;
int lucas(int n,int m)
{
if(m==0) return 1;
return C(n%p,m%p)*lucas(n/p,m/p)%p;
}