【HihoCoder 1475 --- 數組分拆】前綴和+思維遞推

【HihoCoder 1475 --- 數組分拆】前綴和+思維遞推

題目來源:點擊進入【HihoCoder 1475 — 數組分拆】

Description

小Ho得到了一個數組作爲他的新年禮物,他非常喜歡這個數組!

在仔細研究了幾天之後,小Ho成功的將這個數組拆成了若干段,並且每段的和都不爲0!

現在小Ho希望知道,這樣的拆分方法一共有多少種?

兩種拆分方法被視作不同,當且僅當數組斷開的所有位置組成的集合不同。

Input

每組輸入的第一行爲一個正整數N,表示這個數組的長度

第二行爲N個整數A1~AN,描述小Ho收到的這個數組

對於40%的數據,滿足1<=N<=10

對於100%的數據,滿足1<=N<=105, |Ai|<=100

Output

對於每組輸入,輸出一行Ans,表示拆分方案的數量除以(109+7)的餘數。

Sample Input

5
1 -1 0 2 -2

Sample Output

5

解題思路

通過sum[i]來記錄前i個的和。
通過dp[i]來記錄[0,i]中滿足題意的分配方法數。
通過m[x]來記錄前i項和爲x的次數。
cnt記錄i-1項時總的方案數。

首先當我們計算第i項時,我們第i位可以和前面所有方案的最後一段合併,或者自己單獨成爲一段。但是根據題意我們需要去掉中間和爲0的方案,所以減去m[sum[i]]。所以dp[i]=(cnt+1)-m[sum[i]]。

然後更新cnt,使其記錄前i項總共的方案數。即cnt+=dp[i]。
並且更新和爲sum[i]的方案數。

AC代碼(C++):

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <map>
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e5+5;
const int MOD = 1e9+7;
int sum[MAXN],dp[MAXN];

int main(){
    SIS;
    int n,cnt=0;
    map<int,int> m;
    m[0]=1;
    cin >> n;
    for(int i=1;i<=n;i++){
        cin >> sum[i];
        sum[i]+=sum[i-1];
        dp[i]=(cnt+1-m[sum[i]]+MOD)%MOD;
        cnt=(cnt+dp[i])%MOD;
        m[sum[i]]=(m[sum[i]]+dp[i])%MOD;
    }
    cout << dp[n] << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章