组合:
C语言第一个方法
unsigned long long combination(int n,int m)
{
/*
Cnm=n!/(m!*(n-m)!)
*/
unsigned long long ans=1;
if(n==0)
return 0;
if(n==m||m==0)
return 1;
int cnt=2;
if(m>n-m)
{
for(int i=n;i>=m+1;i--)
{
ans*=i;
while(cnt<=n-m&&ans%cnt==0)
{
ans/=cnt;
cnt++;
}
}
}
else
{
for(int i=n;i>=n-m+1;i--)
{
ans*=i;
while(cnt<=m&&ans%cnt==0)
{
ans/=cnt;
cnt++;
}
}
}
return ans;
}
C语言第2个方法(更优)
unsigned long long combination2(int n,int m)
{
//Cnm=n!/(m!*(n-m)!)
unsigned long long ans=1;
int small,large;
int i;
if(n>2*m)//judge n-m>m or not
{
small=m;
large=n-m;
}
else
{
small=n-m;
large=m;
}
for(i=n;i>large;i--)
{
//in this way we can avoid multiplying a lot of even big numbers
if(i==2*small)
{
ans*=2;
small--;
}
else
ans=ans*i;
}
for(i=small;i>1;i--)//divide the rest
ans/=i;
return ans;
}
排列
unsigned long long Permutation(int n,int m)
{
//Pnm=n!/m!
unsigned long long ans=1;
for(int i=m+1;i<=n;i++)
ans*=i;
return ans;
}