题目
GIVEN: 5 <= N <= 100; 5 <= M <= 100; M <= N
Compute the EXACT value of: C = N! / (N-M)!M!
题目大意:就是n中拿m个,有几种情况
思路:鉴于100!=93,326,215,443,944,152,681,699,238,856,266,700,490,715,968,264,381,621, 468,592,963,895,217,599,993,229,915,608,941,463,976,156,518,286,253, 697,920,827,223,758,251,185,210,916,864,000,000,000,000,000,000,000,000
所以要婉转些来。但是用大数处理有很繁琐。Orz!但是,注意到因为分母一定可以约掉分子,所以肯定可以在分子归拢相乘的同时可以先约到最简的模式再相乘!所以可以先找出和分子每一个乘数的最大公约数,上下分子分母约掉!
program1:(模拟)
#include<iostream>
using namespace std;
int m,n;
int low,high;
int a[105];
int gcd(int a,int b)
{
if(a%b==0)return b;
else return gcd(b,a%b); //一开始竟然忘了return,我嚓~~
}
int main()
{
while(scanf("%d%d",&n,&m)&&(n||m))
{
if(m>n-m) //直接模拟排列的运算过程
{
low=m+1;
high=n-m;
}
else
{
low=n-m+1;
high=m;
}
//printf("low high %d %d \n",low,high);
for(int i=1;i<=high;i++)
a[i]=i;
int k,tmp;
__int64 sum=1;
for(int i=low;i<=n;i++)
{
k=i;
for(int j=2;j<=high;j++)
{
tmp=gcd(k,a[j]); //找出最大公约数来约分
if(tmp!=1)
{
k/=tmp;
a[j]/=tmp;// 一开始竟然忘了约掉分母,再嚓~~
}
}
sum*=k;
}
//printf("%lld\n",sum);
printf("%d things taken %d at a time is %I64d exactly.\n",n,m,sum);
}
//system("pause");
return 0;}
program2(DP):
简单DP C(N,M)=C(N-1,M-1)+C(N-1,M);
#include<iostream>
using namespace std;
__int64 mm[102][102];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF ,n||m )
{
memset(mm,0,sizeof(mm));
for(int i=0;i<=n;i++)
mm[i][0]=1;
for(int i=1;i<=n;i++)///
mm[i][i]=1;
for(int i=1;i<=n;i++)
for(int k=1;k<i;k++)///注意k不是1,竟然有数组越界不RE而是WA
{
mm[i][k]=mm[i-1][k-1]+mm[i-1][k];
if(n==i&&m==k)
break;
}
printf("%d things taken %d at a time is %I64d exactly.\n",n,m,mm[n][m]);
//printf("%I64d\n",mm[n][m]);
}
system("pause");
return 0;}