1046: 数组分拆

题目描述

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

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

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

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

输入

多组数据。

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

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

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

对于100%的数据,满足1<=N<=100000, |Ai|<=100
输出
对于每组输入,输出一行Ans,表示拆分方案的数量除以(10^9+7)的余数。

样例输入

5
1 -1 0 2 -2

样例输出

5

#include
using namespace std;
typedef long long ll;
const int N = 1e5+10;
const int mod= 1e9+7;
ll n,ans,dp[N],sum;

map<ll,ll> Hash;

int main(){
    int  i,x;
   while(scanf("%d",&n)!=EOF){
        Hash.clear();sum=0;Hash[0]=1;ans=1;
    for(i=0;i<n;i++){
        scanf("%d",&x);
        sum+=x;
        dp[i]=(ans-Hash[sum]+mod)%mod;
        Hash[sum]=(Hash[sum]+dp[i])%mod;
        ans=(ans+dp[i])%mod;
    }
    printf("%d\n",dp[n-1]);
   }
   return 0;
}

分析

f[i] 等于 f[0] … f[i-1] 中若干项的和。具体是哪些项呢? 是那些满足s[j] != s[i]的f[j]。

比如
num 3 -1 -1 1
sum 3 2 1 2
dp 1 2 4
dp[3]=8-Hash[2]=8-2=6

在sum[i]==sum[j]表示
表示num[i+1]+num[i+2]+…+num[j]==0
由此可知在划分中i+1到j不可划分到一起(和为0)
Hash[sum[i]]记录了0到i的划分方案数,即不可行的
ans-Hash[sum[i]]即为可行方案数

你可能感兴趣的:(1046: 数组分拆)