标签:stream http 集合 https panel lib 礼物 长度 main
小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; }
标签:stream http 集合 https panel lib 礼物 长度 main
原文地址:http://www.cnblogs.com/IMGavin/p/6724937.html