#1475 : 数组分拆

#1475 : 数组分拆

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Ho得到了一个数组作为他的新年礼物,他非常喜欢这个数组!

在仔细研究了几天之后,小Ho成功的将这个数组拆成了若干段,并且每段的和都不为0!

现在小Ho希望知道,这样的拆分方法一共有多少种?

两种拆分方法被视作不同,当且仅当数组断开的所有位置组成的集合不同。

输入

每组输入的第一行为一个正整数N,表示这个数组的长度

第二行为N个整数A1~AN,描述小Ho收到的这个数组

对于40%的数据,满足1<=N<=10

对于100%的数据,满足1<=N<=105, |Ai|<=100

输出

对于每组输入,输出一行Ans,表示拆分方案的数量除以(109+7)的余数。

样例输入
5
1 -1 0 2 -2
样例输出
5
分析:dp[i]代表前i个数方案,sum[i]代表前缀和i;
   dp[i]=∑dp[j](1<=j<i)-∑dp[k](1<=k<i&&sum[k]==sum[i]);
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=1e5+10;
const int N=1e3+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
int n,m,k,t,a[maxn];
ll sum,dp[maxn];
map<int,ll>p;
int main()
{
    int i,j;
    p[0]=1;
    scanf("%d",&n);
    rep(i,1,n)scanf("%d",&a[i]),a[i]+=a[i-1];
    rep(i,1,n)
    {
        dp[i]+=sum+1;
        dp[i]-=p[a[i]];
        (dp[i]+=mod)%=mod;
        sum+=dp[i];
        sum%=mod;
        p[a[i]]+=dp[i];
        p[a[i]]%=mod;
    }
    printf("%lld\n",dp[n]);
    return 0;
}
posted @ 2017-03-06 20:23  mxzf0213  阅读(319)  评论(0编辑  收藏  举报