http://bailian.openjudge.cn/practice/

思路:确定一个数是否选择作为切入点,这可得到一个dp[40][j]=dp[40][j-1]+dp[40-a[j]][j-1]

考查点:精确的选择状态,然后dp;

收获:有记住了一个选择状态的方法;

经验:我做的题还是很少,很难找到准确的状态;

/*#include<stdio.h>
 #include<string.h>
 #include<iostream>
 #include<algorithm>
 using namespace std;


 int n;
 int a[35];


 int main()
 {
     int i,j;
     int m;
     int t;
     int k;
     while(scanf("%d",&n)!=EOF)
     {
         k=0;
         m=(1<<n);
         for(i=0;i<n;i++)
             scanf("%d",&a[i]);
         for(i=1;i<m;i++)
         {
             t=0;
            for(j=0;(1<<j)<=i;j++)
            {
                 if(i&(1<<j))
                     t+=a[j];
            }
            if(t==40)
                 k++;
         }
         printf("%d\n",k);
     }
     return 0;
 }*/
 /*#include<stdio.h>
 #include<string.h>
 #include<iostream>
 #include<algorithm>
 using namespace std;


 int n;
 int a[23];
 int t;


 void rec(int m,int d)
 {
     int i;
     if(m==0)
         t++;
     if(m<=0)
         return;
     for(i=1;i<=d;i++)
         rec(m-a[i],i-1);
 }
 int main()
 {
     int i;
     while(scanf("%d",&n)!=EOF)
     {
         t=0;
         for(i=1;i<=n;i++)
             scanf("%d",&a[i]);
         rec(40,n);
         printf("%d\n",t);
     }
     return 0;
 }*/
 #include<stdio.h>
 #include<string.h>
 #include<algorithm>
 #include<iostream>


 int dp[50][50];
 int a[34];
 int n;


 int main()
 {
     int i,j;
     while(scanf("%d",&n)!=EOF)
     {
         for(i=1;i<=n;i++)
             scanf("%d",&a[i]);
         memset(dp,0,sizeof(dp));
         dp[a[1]][1]=1;
         for(i=2;i<=n;i++)
             for(j=1;j<=40;j++)
             {
                 if(j>a[i])
                     dp[j][i]=dp[j][i-1]+dp[j-a[i]][i-1];
                 else
                 if(j==a[i])
                     dp[j][i]=dp[j][i-1]+1;
                 else
                     dp[j][i]=dp[j][i-1];
             }
         printf("%d\n",dp[40][n]);
     }
     return 0;
 }