#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分析:dp[i]代表前i个数方案,sum[i]代表前缀和i; dp[i]=∑dp[j](1<=j<i)-∑dp[k](1<=k<i&&sum[k]==sum[i]);代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #define rep(i,m,n) for(i=m;i<=n;i++) #define mod 1000000007 #define inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") const int maxn=1e5+10; const int N=1e3+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;} int n,m,k,t,a[maxn]; ll sum,dp[maxn]; map<int,ll>p; int main() { int i,j; p[0]=1; scanf("%d",&n); rep(i,1,n)scanf("%d",&a[i]),a[i]+=a[i-1]; rep(i,1,n) { dp[i]+=sum+1; dp[i]-=p[a[i]]; (dp[i]+=mod)%=mod; sum+=dp[i]; sum%=mod; p[a[i]]+=dp[i]; p[a[i]]%=mod; } printf("%lld\n",dp[n]); return 0; }
时间: 2024-10-06 08:35:22