題目:http://acm.hdu.edu.cn/showproblem.php?pid=1028
整數劃分,每個數可以用無限次;
是以構造 f(x) = (1+x+x2+x3+...)(1+x2+x4+...)(1+x3+x6+...)...(1+xn)
乘起來後的 xn 的系數就是方案數;
用兩個數組做即可,從第一個括号開始一個一個乘,f[i] 表示此時 xi 項的系數,後面每乘過來一個括号,相當于多了一種轉移,是以加上。
代碼如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=125;
int n,f[xn],t[xn];
int main()
{
while(scanf("%d",&n)==1)
{
for(int i=0;i<=n;i++)f[i]=1,t[i]=0;
for(int i=2;i<=n;i++)
{
for(int j=0;j<=n;j++)
for(int k=0;k<=n;k+=i)t[j+k]+=f[j];
for(int j=0;j<=n;j++)f[j]=t[j],t[j]=0;
}
printf("%d\n",f[n]);
}
return 0;
}
題目:http://acm.hdu.edu.cn/showproblem.php?pid=1398
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=305;
int n,f[xn],t[xn];
int main()
{
n=300;
for(int i=0;i<=n;i++)f[i]=1,t[i]=0;
for(int i=2;i<=17;i++)
{
int s=i*i;
for(int j=0;j<=n;j++)
for(int k=0;j+k<=n;k+=s)t[j+k]+=f[j];
for(int j=0;j<=n;j++)f[j]=t[j],t[j]=0;
}
while(1)
{
scanf("%d",&n); if(!n)return 0;
printf("%d\n",f[n]);
}
}