1、关于n!的一个问题。
n!=1*2*3*…*n求,n!中有多少的质因子p
直观的方法为
int ans=0;
for(int i=2;i<=n;i++){
int temp=i;
while(temp%p==0){
temp/=p;
ans++;
}
}
但是其时间复杂度过大,为O(nlog n)
由数学方法可知,n!中有(n/p+n/p^2+…..)个质因子p,其中除法向下取整。
于是得到算法,时间复杂度仅为O(log n)
int ans=0;
while(n){
ans+=n/p;
n/=p;
}
2、组合数的计算
如果直接分别计算n!,m!,(n-m)!,很容易造成溢出。
可以采用递归处理。
代码如下
long long C(long long n,long long m){
if(m==0||n==m){
return 1;
}
else return C(n-1,m-1)+C(n-1,m);
}
还可以通过定义式的变形计算。
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;
}
3、计算
A。通过递推公式计算
int res[1000][1000]={0};
int C(int n,int m,int p){
if(m==0||n==m) return 1;
if(res[n][m]!=0) return res[n][m];//已经有值
return res[n][m]=(C(n-1,m)+C(n-1,m-1))%p;//赋值并返回
}
void calC(){
for(int i=0;i<=n;i++){
res[i][0]=res[i][i]=1;
}
for(int i=2;i<=n;i++){
for(int j=0;j<=i/2;j++){
res[i][j]=(res[i-1][j]+res[i-1][j-1])%p;
res[i][i-j]=res[i][j];
}
}
}