【前缀和 && 思维转换】ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined)Molly's Chemicals

Problem Description

输入n, k代表有n个元素,问你任意取一段区间和 满足k的m次方(m是任意正整数)让你求出:有多少段不同的区间和?

思路:

第一想法能想到的就是前缀和然后 sum[i] - sum[j] = pow[k] i: 1 to n; j : 0 to (i - 1); k : 0 to m;这样复杂度肯定会超时。于是就没想到了,然后百度借鉴借鉴。将公式转化成sum[i] - pow[k] = sum[j]这样i: 1 to n; k: 0 to m; j: 0 to (i - 1); 这时候 j可以在跑i的时候处理一下,复杂度就降到了n * m就够了注意inf的范围。

#include<bits/stdc++.h>
using namespace std;
#define nn 100055
#define inf 200000000000005//最大的两倍因为有负数
long long sum[nn];//前缀和
long long Pow[nn];//用来存k的m次方
int main()
{
    int n, i, j, m;
    long long k, num;
    while(~scanf("%d %lld", &n, &k))
    {
        map<long long, int> q;
        memset(sum, 0, sizeof(sum));
        for(i = 1; i <= n; i++)//求前缀和
        {
            scanf("%lld", &num);
            sum[i] = sum[i - 1] + num;
        }
        Pow[0] = 1;//求k的m次方
        m = 0;
        if(k != 1 && k != -1)//k得判断下特殊情况1 和 -1
        for(i = 1; abs(Pow[i-1] * k) < inf; i++)
        {
            Pow[i] = Pow[i - 1] * k;
            m = max(m, i);
        }
        else if(k == -1)
        {
            Pow[1] = -1; m = 1;
        }


        q[0] = 1;//相当于sum[0]
        long long ans = 0;
        for(i = 1; i <= n; i++)
        {
            for(j = 0; j <= m; j++)
            {
                long long d = sum[i] - Pow[j];
                if(q.count(d))//如果存在
                    ans += q[d];//更新ans
            }
            if(q.count(sum[i]))//在跑i的过程 处理sum[j]这样复杂度就降下来了
                q[sum[i]]++;
            else q[sum[i]] = 1;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值