题目大意:
给你一个长度为N的序列,可以将任意数加上一个正号或者是负号.
求一共有多少个连续的子序列和为0.
思路:
1、统计计数问题,考虑dp:
①设定dp【i】【j】表示进行到第i位,和为j的方案数。
②考虑到会有负数和的情况出现,并且观察到题目保证a1+a2+a3+a4+................不会超过10000.那么显然,如果我们对所有数字都加上了负号,那么对应和不会小于-10000.
那么我们知道数组下标都是正的才行,那么我们考虑将15000设定为0.对应dp【i】【15000】就是表示加到第i位和为0的情况数。
2、那么接下我们考虑状态转移方程:
①dp【i】【j】+=dp【i-1】【j-a【i】】;
②dp【i】【j】+=dp【i-1】【j+a【i】】;
表示我们当前第i位的和紧接着上一位的和延续下去。
③dp【i】【15000+a【i】】=1;
④dp【i】【15000-a【i】】=1;
表示当前第i位的和独立出来,作为起点。
3、注意取模。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define mod 1000000007
int a[1005];
int dp[1005][30000];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
dp[1][15000+a[1]]=1;
dp[1][15000-a[1]]=1;
for(int i=2;i<=n;i++)
{
dp[i][15000+a[i]]=1;
dp[i][15000-a[i]]=1;
for(int j=0;j<30000;j++)
{
dp[i][j]=(dp[i][j]+dp[i-1][j-a[i]])%mod;
dp[i][j]=(dp[i][j]+dp[i-1][j+a[i]])%mod;
}
}
int output=0;
for(int i=1;i<=n;i++)
{
output=(output+dp[i][15000])%mod;
}
printf("%d\n",output);
}
}