codeforces 776C

来源:互联网 发布:修真淘宝大户 编辑:程序博客网 时间:2024/06/05 04:49

题目链接:codeforces 776C

题目大意:一个数列,有n个元素,求有多少个连续区间,区间和为k^0,k^1,k^2…..

一开始的时候想到了sum数组存储前n项和,但如果遍历所有区间的话,复杂度为n^2
然后想到了对于每个sum[i],只要在前面找到一个sum[j], j<i,满足sum[i] - sum[j] = k^x(x>=0);
所以我用map<int, vector<int> > mapp存储每个sum值出现的位置,所以,对于每个sum[i], 遍历mapp[k^x - sum[i]],当mapp[k^x - sum[i] ][j] 0<=j<mapp[k^x - sum[i]].size(),当mapp[k^x - sum[i] ][j] < i时,(即前面存在一个sum[i'],使得sum[i] - sum[i'] = k^x),答案加一,但还是会超时。

看了别人的代码才想到,每次只需用的sum[i] 前面的sum,不需要开始就把所有的情况存入mapp,只需要每次把第i个存入就好了。这样就不需要遍历mapp[k^x - sum[i]]在判断了,因为此时里面元素都是在i之前的。

特别要注意k==1 || k==-1的情况

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<map>#include<vector>using namespace std;const int MAXN = 100000 + 100;typedef long long ll;const ll INF = 1e15;map<ll, ll> mapp;ll a[MAXN], sum[MAXN];ll n, k;int main(){    cin >> n >> k;    sum[0] = 0;    for(int i=1; i<=n; ++i)    {        scanf("%I64d", a+i);        sum[i] = sum[i-1] + a[i];    }    ll cnt = 0;    ll t = k;    mapp[0] = 1;    int nn = 60;    if(t==1) nn = 1;    else if(t==-1) nn = 2;    k = 1;    for(int i=1; i<=n; ++i)    {        for(int x=1; k>=-INF && k<=INF && x <=nn; ++x)        {            ll a = sum[i] - k;            if(mapp.find(a) != mapp.end()) cnt += mapp[a];            k*=t;        }        k=1;        mapp[sum[i]]++;    }    cout << cnt << endl;    return 0;}
0 0
原创粉丝点击