【题意】给定一个数top及最底层元素个数n,构成一个以给top为塔尖,层数为n的如杨辉三角的金字塔,求有多少种
【分析】最终种数其实只与最底层的n个数的组合数有关,上层的每个都数是由最底层数相加得来
以层数4为例
设最底层 x1,x2,x3,x4
则第二层x1+x2,x2+x3,x3+x4
第三层x1+2*x2+x3, x2+2*x3+x4
最高层 x1+3*x2+3*x3+x4
可以看出 1 3 3 1 为 C(3,0) C(3,1) C(3,2) C(3,3)
所以问题可以看做是一个以 C(n-1,0) C(n-1,1).....C(n-1,n)为单个物品容量,容量和为2^(n-1),top为背包总容量的完全背包问题,其中由于最底层数均大于一,所以每个背包至少被装一次。
又由于背包最大有10^6,所以n应小于20
【代码】
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> int v[1000050]; int c[1000050]; using namespace std; int length,top,total; const int mod=1000000009; void init(int n) { total=1; memset(c,0,sizeof(c)); c[0]=1; for(int i=1;i<=n;i++) { c[i]=c[i-1]*(n+1-i)/i; total+=c[i]; } } int main (void) { while(scanf("%d%d",&length,&top)==2) { if(length>20) { printf("0 "); continue; } init(length-1); if(top<total) { printf("0 "); continue; } memset(v,0,sizeof(v)); v[0]=1; for(int i=0;i<length;i++) { for(int j=c[i];j<=top-total;j++) v[j]=(v[j]+v[j-c[i]])%mod; } printf("%d ",v[top-total]%mod); } return 0; }最初想的是每一层的元素都是由该层第一个数决定,所以只需找出每层第一个数组成的排列种数,可是不会写代码,写了个递归可是组合数稍微大一点就慢死。
所以弱渣还是要多观察多思考。