G(x)=(1+x+x2+x3+x4+…)(1+x4+x8+x12+…)(1+x9+x18+x27+…)…
典型母函数!
//HDOJ_1398 Square Coins //G(x)=(1+x+x^2+x^3+x^4+…)(1+x^4+x^8+x^12+…)(1+x^9+x^18+x^27+…)… #include <iostream> using namespace std; const int lmax=300; int c1[lmax+1],c2[lmax+1]; int main(void) { int n,i,j,k; while (cin>>n &&n) { for (i=0;i<=n;i++) { c1[i]=1; c2[i]=0; }//1 for (i=2;i<=17;i++)//2 { for (j=0;j<=n;j++)//3 for (k=0;k+j<=n;k+=i*i)//4 { c2[j+k]+=c1[j]; } for (j=0;j<=n;j++)//5 { c1[j]=c2[j]; c2[j]=0; } } cout<<c1[n]<<endl; } return 0; }
几点说明:第i个括号里面的指数为K的系数为j
1: 对c1初始化,由第一个表达式(1+x+x2+..x^17)初始化,把质量从0到17的所有硬币个数都初始化为1.
2: i从2到n遍历,一次模拟手工打开括号,从第二个到低17个括号
3:j
从0到n遍历,这里j就是里第j个变量的系数。.
4: k表示的是第j个指数,所以k每次增i*i
5:为打开下一个括号准备
//HDOJ_1398 Square Coins //变化一点点,灵活多多多 … int main(void) { int n,i,j,k; int elem[17]={1,4,9,16,25,36,…,169,196,225,256,289} while (cin>>n && n!=0) { for (i=0;i<=n;i++) { c1[i]=1; c2[i]=0; } for (i=2; i<=17; i++) { for (j=0;j<=n;j++) for (k=0;k+j<=n; k+=elem[i-1] ) { c2[j+k]+=c1[j]; } for (j=0;j<=n;j++) { c1[j]=c2[j]; c2[j]=0; } } cout<<c1[n]<<endl; } return 0; }
变化一下就可以敢好多事情啦!
杭电1028:
//整数拆分。由于拆分结果只考虑有几个1几个2几个3...Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem.问题就和之前的砝码邮票什么的一样了。 //G(x)=(1+x+...)(1+x^2+...)(1+x^3....)...(1+x^n) #include <iostream> using namespace std; const int lmax=120; int c1[lmax+1],c2[lmax+1]; int main(void) { int n,i,j,k; while (cin>>n ) { for (i=0; i<=n; i++) { c1[i]=1; //1 c2[i]=0; } for (i=2; i<=n; i++) //每个有n个 { for (j=0; j<=n; j++) //3 for (k=0; k+j<=n; k+=i) //4 { c2[j+k]+=c1[j]; } for (j=0; j<=n; j++) //5 { c1[j]=c2[j]; c2[j]=0; } } cout<<c1[n]<<endl; } return 0; }
看完上面也许觉得还是不太明白,有点感觉自己蒙混过关的意思,下面看完下面这个题就是很傻逼的方法:
//HDOJ1085 //G(x)=(1+x+x^2+...+x^a)*(1+x^2+x^4...+x^2b)*(1+x^5+x^10+...+x^5c) #include <iostream> using namespace std; const int lmax=8000; int c1[lmax+1],c2[lmax+1]; int main(void) { int i,j,k,a,b,c; while (cin>>a >> b >> c,a||b||c)//这种写法简练 { for (i=0; i<=lmax; i++) { c1[i]=1; c2[i]=0; } for(i=0; i<=a*1; i++) c1[i]=1;//第一个括号的系数 for(i=0; i<=a; i++) for(j=0;j<=b*2; j+=2) c2[i+j]+=c1[j]; for(i=0;i<=a+(b*2);i++)//刷新一下 { c1[i]=c2[i]; c2[i]=0; } for(i=0;i<=a+(b*2);i++) for(int j=0;j<=c*5;j+=5) c2[i+j]+=c1[i]; for(i=0;i<=a+(b*2)+(c*5);i++) { c1[i]=c2[i]; c2[i]=0; } for(i=0;i<=a+(b*2)+(c*5);i++) { if(c1[i]==0)//不能支付 { cout << i << endl; break; } } if(i==a+(b*2)+(c*5)+1) cout << i << endl;//可以支付前面所有的 } return 0; }