hihocoder 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

首先想到O(n^2)的dp,dp[i] += dp[j] , j < i && sum[i] != sum[j]
优化一下就可得到o(n)的算法,先加上再减去.


//http://www.cnblogs.com/IMGavin/
//https://hihocoder.com/problemset/problem/1475
#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#include <algorithm>
using namespace std;

typedef long long LL;
#define gets(A) fgets(A, 1e8, stdin)
const int INF = 0x3F3F3F3F, N = 100008, MOD = 1000000007;
const int M = 20000008;
const int P = 1e7;
const double EPS = 1e-6;
int a[N];
LL dp[N];
LL ds[N];

LL sum[N];
int tot = 0;
int s2[M];

int main(){
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++){
		scanf("%d", &a[i]);
		sum[i] = sum[i -1] + a[i];
	}
	dp[0] = 1;
	ds[0] = 1;
	s2[10000000] = 1;
	for(int i = 1; i <= n; i++){
		dp[i] = (ds[i - 1] - s2[sum[i] + 10000000] + MOD) % MOD;
		(s2[sum[i] + 10000000] += dp[i]) %= MOD;
		ds[i] = (ds[i - 1] + dp[i]) % MOD;
	}
	cout<<dp[n]<<endl;
	return 0;
}

  



posted @ 2017-04-17 21:18  vwirtveurit  阅读(749)  评论(0编辑  收藏  举报