题意:
给出一个值n,问有几种不同的拆分方法。
要点:
可以用母函数或DP来做,这里说一下母函数,基本思路是:写成(1+x^2+x^3+x^4……x^n)*(1+x^2+x^4+……)*(1+x^3+x^6+……)……这样,然后利用循环从每个括号开始算起,用c1存储前一次算出的所有指数对应的系数,c2暂存算上当前括号的对应系数,最后c1[n]就是答案。
母函数:
18281776 | 2016-09-18 09:36:22 | Accepted | 1028 | 0MS | 1568K | 693 B | G++ | seasonal |
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,i,j,k;
while(scanf("%d",&n)!=EOF)
{
int c1[125],c2[125];
for(i=0;i<=n;i++)//一开始所有指数的系数都是1
{
c1[i]=1;//c1表示未算当前括号内的前面元素的系数
c2[i]=0;//c2表示算上当前括号的总和,是个暂存的数组
}
for(i=2;i<=n;i++)//从第2个括号开始算起,第一个都是1不用算
{
for(j=0;j<=n;j++)//计算所有指数
{
for(k=0;k+j<=n;k+=i)//第i个括号中每个元素与前面已经算出的元素相乘,指数变化
{
c2[k+j]+=c1[j];
}
}
for(j=0;j<=n;j++)//系数保存在前一个数组内
{
c1[j]=c2[j];
c2[j]=0;
}
}
printf("%d\n",c1[n]);
}
return 0;
}
DP:
基本思路是dp[i][j]表示i被拆分为最大因数为j的方法数,然后分为使用j和不用j两种。
18282153 | 2016-09-18 10:28:03 | Accepted | 1028 | 0MS | 1636K | 613 B | G++ | seasonal |
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[125][125];//dp[i][j]表示i被拆分为最大因数为j的方法数
int cal(int n,int m)
{
if(dp[n][m]!=-1)
return dp[n][m];
if(n<1||m<1)
return dp[n][m]=0;
if(n==1&&m==1)
return dp[n][m]=1;
if(n<m)
return dp[n][m]=cal(n,n);
if(n==m)
return dp[n][m]=cal(n,m-1)+1;//自己整个作为一种
return dp[n][m]=cal(n,m-1)+cal(n-m,m);//有两种情况,使用m或不使用m
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(dp,-1,sizeof(dp));
printf("%d\n",cal(n,n));
}
return 0;
}