普通型: 1.求每种数字个数无限个,求组成N的组合数,例如2为两个1+1和2。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include<utility>
#include<sstream>
#include<cmath>
#include <algorithm>
using namespace std;
int a[100001],b[100001];
// a是保存各项质量砝码可以组合的数目
// b是中间量,保存每一次的情况
int main()
{
int n;
while(~scanf("%d",&n))//此时的n是第一个括号的所有项个数
{
memset(a,0,sizeof(a));
//我们用下标来表示砝码重量,用a[i]值来表示i的数量
for(int i=0; i<=n; i++)
{
a[i]=1;
b[i]=0;
}
for(int i=2; i<=n; i++) //n 括号个数
{
for(int j=0; j<=n; j++) //j是第一个括号里的每一项x^j的指数j
{
for(int k=0; k+j<=n; k+=i) //k第二个括号的每一项x^k的指数
{
b[j+k]+=a[j];//目前的第一括号与第二括号两两相乘
}//由于第二括号的系数全为1,相乘后的系数就是a[j],累加即可
}
for(int j=0; j<=n; j++)
{// 把b中的值给a,并把b清0
a[j]=b[j];
b[j]=0;
}
}
printf("%d\n",a[n]);//输出能组成nNum大小的方案数
}
return 0;
}
2.三种硬币价值分别为1 2 5,数目输入。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include<utility>
#include<sstream>
#include<cmath>
#include <algorithm>
using namespace std;
int b1[100001],b[100001];
int a1[100001];
// b1是保存各项质量砝码可以组合的数目
// b是中间量,保存每一次的情况
//b1的下标表示的是每一项x^i的系数,函数中的每一项系数
int main()
{
int aa,bb,c;;
while(~scanf("%d%d%d",&aa,&bb,&c))
{
if(aa==0&&bb==0&&c==0)
return 0;
memset(a1,0,sizeof(a1));
memset(b,0,sizeof(b));
memset(b1,0,sizeof(b1));
//我们用下标来表示砝码重量,用a1[i]值来表示i的数量
//价值1的有aa个,2的有bb个,5的有c个。
a1[1]=aa;
a1[2]=bb;
a1[5]=c;
int maxx=1*aa+bb*2+c*5;
//maxx记下所有砝码可以组成的最大重量,即总和最大
for(int i=0;i<=aa;i++)
{
b1[i]=1;
b[i]=0;
}
int temp=aa;//始终代表第一括号的最大的指数
for(int i=2;i<=5;i++)
{
if(a1[i]==0)//i重量砝码有0个,所以没必要计算
continue;
for(int j=0;j<=temp;j++)
{//j是第一个括号里的每一项x^j的指数
for(int k=0;k<=a1[i]*i;k+=i)
{//k第二个括号的每一项x^k的指数
b[j+k]+=b1[j];//目前的第一括号与第二括号两两相乘
}
}
/*上面的k<=a1[i]*i 表示第二括号的结束条件,
a1[i]*i是目前的第二括号最大指数*/
//temp总是记下第一括号的最大的x^j的指数j,便于下一次循环作为结束条件
temp+=a1[i]*i;
for(int j=0;j<=maxx;j++)
{
b1[j]=b[j];
b[j]=0;
}
}
//计算完成后就得到了每一种重量的方案数,存在b1中
for(int i=1;i<=maxx+1;i++)
{
if(b1[i]==0)
{
printf("%d\n",i);
break;
}
}
}
return 0;
}
指数型:模板题 http://acm.hdu.edu.cn/showproblem.php?pid=1521
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
int a[1001],b[1001];double c[1001],d[1001];
//因为用到了除法,所以用double型来存储。
void ddd()
{
b[0]=1;
b[1]=1;
for(int i=2;i<=31;i++)//记录各个位置的阶乘数
{
b[i]=b[i-1]*i;
}
}
int main()
{
int n,m;
ddd();
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
for(int i=0;i<=a[1];i++)
{
c[i]=1.0/b[i];
}
for(int i=2;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int k=0;k+j<=m&&k<=a[i];k++)
{
d[j+k]+=c[j]/b[k];//这里注意
}
}
for(int j=0;j<=m;j++)
{
c[j]=d[j];
d[j]=0;
}
}
printf("%.lf\n",c[m]*b[m]);//还原
}
return 0;
}