【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;
}