首页 > 代码库 > hdu1398(母函数或者DP)

hdu1398(母函数或者DP)

题目意思:

      有一个序列a[17]=(1,4,9.....,i*i,17*17),对于给出的数字n,求出用给定的序列组合成n的个数。

http://acm.hdu.edu.cn/showproblem.php?pid=1398


题目分析:

该题可以用母函数模板或者DP

DP转化方程    if(dp[j]==1) dp[j+i*i]=1;//记录是否可以到达

                                          res[j+i*i]+=res[j];//记录种类数

母函数:只需要修改模板即可,类似hdu1028,祥见源代码


AC代码:


/**
 *母函数或者DP
 *母函数解题报告:
 *题意和HDU1028差不多但是这个题限制了只能是一个数的平方
 *例如第二个样例10的拆分数是这样算出来的就是求:
 *(1+x+x^2+x^3+x^4+x^5+x^6+x^7+x^8+x^9+x^10)(1+x^4+x^8)(1+x^9)中
 *x^10的系数即可,也是套用母函数模板,只是把把i<=n改成了i*i<=n,
 *在k遍历指数时把k=k+i变成了k=k+i*i(因为指数增加的时候是“相加“型,
 *例:x^9*x^27=x^36);就AC了!
 */
#include<iostream>
#include<cstring>
using namespace std;
/**母函数
int main()
{
    int a[350],b[350],i,j,k,n;
    while(cin>>n&&n)
    {
        for(i=0;i<=n;i++){
            a[i]=1;
            b[i]=0;
        }
        for(i=2;i<=17;i++){
            for(j=0;j<=n;j++)
                for(k=0;k+j<=n;k+=i*i)
                    b[k+j]+=a[j];
            for(j=0;j<=n;j++){
                a[j]=b[j];
                b[j]=0;
            }
        }
        cout<<a[n]<<endl;
    }
    return 0;
}**/
/**
 *DP转化方程
 *if(dp[j]==1) dp[j+i*i]=1; res[j+i*i]+=res[j];//记录种类数
 */
int main()
{
    int dp[305],res[305],n;
    memset(dp,0,sizeof(dp));
    memset(res,0,sizeof(res));
    dp[0]=res[0]=1;
    for(int i=1;i<=17;i++){
        for(int j=0;j+i*i<=300;j++){
            if(dp[j]){
                dp[j+i*i]=dp[j];
                res[j+i*i]+=res[j];
            }
        }
    }
    while(cin>>n&&n){
        cout<<res[n]<<endl;
    }
    return 0;
}


hdu1398(母函数或者DP)