poj 1306 Combinations
递归
#include<iostream>//递归
usingnamespace std;
__int64 ans[200][200];
__int64 f(int n,int m)
{
if(ans[n][m]>0)
return ans[n][m];
if(n==m||m==0)
return1;
ans[n][m]=f(n-1,m)+f(n-1,m-1); //C(n,m)=C(n-1,m)+C(n-1,m-1)
return ans[n][m];
}
int main()
{
int n,m;
while(cin>>n>>m&&n)
{
memset(ans,0,sizeof(ans));
printf("%d things taken %d at a time is %I64d exactly.\n",n,m,f(n,m));
}
return0;
}
数据规模小,直接计算
#include<iostream>
usingnamespace std;
int main()
{
double n,m,i,j,res;
while(cin>>n>>m&&n)
{
res=1;
double r1=1,r2=1;
for(i=n-m+1,j=1;i<=n;i++,j++) // res = (n-m+1)*(n-m+2)*...*n / 1*2*...*m
{
r1*=i;
r2*=j;
}
res=r1/r2;
printf("%.0f things taken %.0f at a time is %.0f exactly.\n",n,m,res);
}
return0;
}
#include<iostream>
usingnamespace std;
int main()
{
double n,m,i,j,res;
while(cin>>n>>m&&n)
{
res=1;
for(i=n-m+1,j=1;i<=n;i++,j++) // res = (n-m+1)*(n-m+2)*...*n / 1*2*...*m
{
res*=i/j;
}
printf("%.0f things taken %.0f at a time is %.0f exactly.\n",n,m,res);
}
return0;
}
高精度
// 题意:求组合数C(n,m) = n! / (n-m)!m!
#include <iostream>
#include <string>
using namespace std;
int compare(string str1, string str2)
{
while(!str1.empty()&&str1[0]=='0')
{
str1.erase(0,1);
}
while(!str2.empty()&&str2[0]=='0')
{
str2.erase(0,1);
}
if(str1.size() > str2.size()) //长度长的整数大于长度小的整数
return 1;
else if(str1.size() < str2.size())
return -1;
else
return str1.compare(str2); //若长度相等,从头到尾按位比较,compare函数:相等返回0,大于返回1,小于返回-1
}
int to_int(char ch)
{
return ch-48;
}
char to_char(int i)
{
return (char)(i+48);
}
string to_str(int n)
{
string str;
while(n)
{
str.insert(str.begin(),n%10+48);
n=n/10;
}
return str;
}
void dipose_head(string& str,int sign) //str为引用类型
{
str.erase(0, str.find_first_not_of('0')); //去除结果中的前导0
if(str.empty()) str = "0";
if((sign == -1) && (str[0] != '0')) //处理符号位 ,若str[0] == '0'说明结果是0,就不必要在前面加上-
str = '-' + str;
}
//高精度加法
string ADD_INT(string str1, string str2) //计算str1 + str2的值,处理成 str1 ,str2 >= 0
{
if(str1.empty()) str1="0";
if(str2.empty()) str2="0";
string MINUS_INT(string str1, string str2); //要事先声明MINUS_INT
string str;
if(str1[0] == '-')
{
if(str2[0] == '-')
{
str = ADD_INT(str1.erase(0, 1), str2.erase(0, 1));
if(str[0] != '0')
str = "-" + str;
}
else
str = MINUS_INT(str2, str1.erase(0, 1));
}
else
{
if(str2[0] == '-')
str = MINUS_INT(str1, str2.erase(0, 1));
else //str1 ,str2 >= 0的情况
{
string::size_type l1, l2;
int i;
l1 = str1.size(); l2 = str2.size();
if(l1 < l2) //把两个整数对齐,短整数前面加0补齐
for(i = 1; i <= l2 - l1; i++)
str1 = '0' + str1;
else
for(i = 1; i <= l1 - l2; i++)
str2 = '0' + str2;
int int1 = 0, int2 = 0; //int2 记录进位
for(i = str1.size() - 1; i >= 0; i--)
{
int1 = ( str1[i]+str2[i] - 96 + int2 ) % 10;
int2 = ( str1[i]+str2[i] - 96 + int2 ) / 10;
str = to_char(int1) + str;
}
if(int2 != 0) str = to_char(int2) + str; //处理最后的进位
}
}
return str;
}
//高精度减法
string MINUS_INT(string str1, string str2) //计算str1 - str2的值,先处理成 str1 ,str2 >= 0,再处理成 str1 > str2 >= 0
{
if(str1.empty()) str1="0";
if(str2.empty()) str2="0";
int sign = 1; //sign 为符号位
string str;
if(str2[0] == '-')
{
if(str1[0]!='-')
str = ADD_INT(str1, str2.erase(0, 1));
else
str=MINUS_INT(str2.erase(0,1),str1.erase(0,1));
}
else
{
if(str1[0]=='-')
{
str = ADD_INT(str1.erase(0, 1), str2);
if(str[0] != '0')
str = "-" + str;
}
else //str1 ,str2 >= 0的情况
{
int res = compare(str1, str2);
if(res == 0) return "0"; //二者相等
if(res < 0)
{
sign = -1;
str1.swap(str2);
}
string::size_type temp_int;
temp_int = str1.size() - str2.size();
int cf=0; //cf保存借位
for(int i = str2.size() - 1; i >= 0; i--)
{
if(str1[i + temp_int] - cf < str2[i])
{
str = to_char(str1[i + temp_int] - cf - str2[i] + 10) + str;
cf=1;
}
else
{
str =to_char(str1[i + temp_int] - cf - str2[i]) + str;
cf=0;
}
}
for(int i=temp_int-1;i>=0;--i)
{
if(str1[i]-cf>='0') //看是否够借位减
{
str=char(str1[i]-cf)+str;
cf=0;
}
else
{
str=char(str1[i]-cf+10)+str;
cf=1;
}
}
dipose_head(str,sign);
}
}
return str;
}
//高精度乘法
string MULTIPLY_INT(string str1, string str2)
{
if(str1.empty()) str1="0";
if(str2.empty()) str2="0";
int sign = 1; //sign 为符号位
if(str1[0] == '-')
{
sign *= -1;
str1 = str1.erase(0, 1);
}
if(str2[0] == '-')
{
sign *= -1;
str2 = str2.erase(0, 1);
}
if(str1=="0"||str2=="0") return "0";
int i, j; string str;
string::size_type len1, len2;
len1 = str1.size(); len2 = str2.size();
for(i = len2 - 1; i >= 0; i --) //实现手工乘法
{
string temp_str;
int int1 = 0, int2 = 0, int3 = to_int(str2[i]);
if(int3 != 0)
{
for(j = 1; j <= len2-1 - i; j++)
temp_str = '0' + temp_str;
for(j = len1 - 1; j >= 0; j--)
{
int1 = (int3 * to_int(str1[j]) + int2) % 10;
int2 = (int3 * to_int(str1[j]) + int2) / 10;
temp_str = to_char(int1) + temp_str;
}
if(int2 != 0) temp_str = to_char(int2) + temp_str;
}
str = ADD_INT(str, temp_str);
}
if((sign == -1) && (str[0] != '0'))
str = '-' + str;
return str;
}
//高精度除法
string DIVIDE_INT(string str1, string str2, int flag) //flag = 1时,返回商; flag = 0时,返回余数
{
if(str1.empty()) str1="0";
if(str2.empty()) str2="0";
string quotient, residue; //定义商和余数,sign1,sign2判断商和余数的符号
int sign1 = 1, sign2 = 1;
if(str2 == "0") //判断除数是否为0
return "ERROR!";
if(str1 == "0") //判断被除数是否为0
return "0";
if(str1[0] == '-')
{
str1 = str1.erase(0, 1);
sign1 *= -1;
sign2 = -1; //余数的符号由被除数的符号决定
}
if(str2[0] == '-')
{
str2 = str2.erase(0, 1);
sign1 *= -1;
}
int res = compare(str1, str2);
if(res < 0)
{
quotient = "0";
residue = str1;
}
else if(res == 0)
{
quotient = "1";
residue = "0";
}
else //str1>str2
{
string::size_type len1, len2;
len1 = str1.size(); len2 = str2.size();
string temp_str;
temp_str.append(str1, 0, len2 - 1); //添加从str1[0]到str1[len2 - 2]
for(int i = len2 - 1; i < len1; i++) //模拟手工除法
{
temp_str = temp_str + str1[i];
for(char ch = '9'; ch >= '0'; ch --) //试商
{
string str;
str = str + ch;
if(compare(MULTIPLY_INT(str2, str), temp_str) <= 0)
//在compare增添的两个while()语句在这里发挥作用,倘若缺失,比如计算10/1,第二次的temp_str=00,按照compare函数的定义,00就会比1大了
{
quotient = quotient + ch;
temp_str = MINUS_INT(temp_str, MULTIPLY_INT(str2, str));
break;
}
}
}
residue = temp_str; //residue就不用判断前面是否带0,因为temp_str = MINUS_INT(...),MINUS_INT把0处理了
if(quotient[0]=='0')
quotient.erase(0,1); //商前面最多只有一个0
}
if((sign1 == -1) && (quotient!="0")) quotient = "-" + quotient;
if((sign2 == -1) && (residue != "0")) residue = "-" + residue;
if(flag == 1)
return quotient;
else
return residue;
}
string a_multiply_b(int a,int b) //a*...*b
{
string str=to_str(a),tmp;
for(int i=a+1;i<=b;i++)
{
tmp=to_str(i);
str=MULTIPLY_INT(str,tmp);
}
return str;
}
int main()
{
int n,m;string m1,m2;
while(scanf("%d%d",&n,&m)&&n)
{
if(n==m)
printf("%d things taken %d at a time is 1 exactly.\n",n,m);
else
{
if(n-m<m)
{
m1=a_multiply_b(m+1,n);
m2=a_multiply_b(1,n-m);
}
else
{
m1=a_multiply_b(n-m+1,n);
m2=a_multiply_b(1,m);
}
cout<<n<<" things taken "<<m<<" at a time is "<<DIVIDE_INT(m1,m2,1)<<" exactly.\n";
}
}
return 0;
}