Codeforces 776C

题目大意:给出n个数(a1.....an),和一个数k,问有多少个区间的和等于k的幂 (1 ≤ n ≤ 10^5, 1 ≤ |k| ≤ 10, - 10^9 ≤ ai ≤ 10^9)

解题思路:首先,可以从题目得出k的幂最大不能超过n*ai=1e14。然后,我们先求出前缀和sum[1]...sum[n],k的i次幂为power[i]。我们要求出一个区间和等于power[i]即sum[r]-sum[l]=power[i],转换一下sum[r]=sum[l]+power[i]。

所以我们只需要从1到n遍历一遍,记录下sum[r]的出现次数,用map存起来,即map[sum[i]+power[i]]++。最后如果sum[r]可以从我们的sum[1]到sum[n]这些前缀和里找到,那就把ans+=map[sum[r]]。

代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<map>
 4 using namespace std;
 5 typedef long long ll;
 6 const int N = 1e5 + 5;
 7 
 8 ll sum[N];//前缀和
 9 ll power[60];
10 
11 int main() {
12     ll n, k;
13     cin >> n >> k;
14     sum[0] = 0;
15     map<ll, ll>mp;
16     for (int i = 1; i <= n; i++) {
17         cin >> sum[i];
18         sum[i] += sum[i - 1];
19     }
20 
21     ll t = 1;
22     ll cnt = 0;
23     power[0] = 1;
24     //1和-1需要特判 
25     if (k == 1 || k == -1) {
26         if (k == -1) {
27             power[1] = -1;
28             cnt++;
29         }
30     }
31     else {
32         for (int i = 1; i <= 50; i++) {
33             t *= k;
34             if (t>1e14)
35                 break;
36             power[++cnt] = t;
37         }
38     }
39     //sum[l]=0时的情况
40     for (int i = 0; i <= cnt; i++) {
41         mp[power[i] + 0]++;
42     }
43 
44     ll ans = 0;
45     for (int i = 1; i <= n; i++) {
46         //计算ans一定要写在这里
47         ans += mp[sum[i]];
48         //记录sum[r]=sum[l]+power[j]的出现次数
49         for (int j = 0; j <= cnt; j++) {
50             mp[sum[i] + power[j]]++;
51         }
52     }
53     cout << ans << endl;
54     /*这种写法是错误的,因为sum[r]一定在sum[l]之后,可能出现sum[l]+power[i]得到的值不在sum[l]后面,
55     而在sum[l]前面,那么也就不满足是sum[r]的条件了,下面这样写就会把这种情况也记录在内了。
56     for (int i = 1; i <= n; i++) {
57         ans += mp[sum[i]];
58     }
59     cout << ans << endl;
60     */
61     return 0;
62 }
原文地址:https://www.cnblogs.com/fu3638/p/7106392.html