n个数(1..1000),从这串数中选取一个字串,任意添加数前的正负号,若以一种方案加上符号后该字串的和为0,则是一种可行的方案,问对这n个数共有多少种可行的方案(字串大小任意,至少为2(1个数怎么也凑不出0...))。n个数的和不超过10000.一般情况下,题目的条件都是有用的,这道题就是从n个数的和不超过10000入手.dp[i][j]记录以第i个数为终点,此时和为j的方案数.转移方程dp[i][j+a[i]]+=dp[i-1][j],dp[i][j-a[i]]-=dp[i-1][j]..边界dp[i][0]=1,因为空串不是符合要求的方案,所以在统计答案的时候要把每个dp[i][0]减掉1..n个数的和不超过10000,所以复杂度是1000*20000的,带着取模的操作,在cf上跑了100ms,只能说cf的服务里太强了...
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;
int dp[1010][20200];
int n,m,p,q;
int a[1010];
int sum;
const int mod=1000000007;
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d",&n);
sum=0;
for (int i=1; i<=n; i++)
scanf("%d",&a[i]),sum+=a[i];
memset(dp,0,sizeof dp);
dp[0][0+sum]=1;
for (int i=1; i<=n; i++)
dp[i][0+sum]=1;
for (int i=1; i<=n; i++)
{
for (int j=-sum; j<=sum; j++)
if (dp[i-1][j+sum])
{
dp[i][j+sum+a[i]]+=dp[i-1][j+sum];
dp[i][j+sum+a[i]]%=mod;
dp[i][j+sum-a[i]]+=dp[i-1][j+sum];
dp[i][j+sum-a[i]]%=mod;
}
// for (int j=-sum; j<=sum; j++)
// cout<<dp[i][j+sum]<<" ";
// cout<<endl;
}
int ans=0;
for (int i=1; i<=n; i++)
ans+=dp[i][0+sum]-1,ans%=mod;
cout<<ans<<endl;
return 0;
}