题目意思:
有一个序列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;
}