codeforces 776C

题目链接: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值