思路:这种问区间和的问题无疑是要用前缀和的了,然后如果n^2暴力枚举区间肯定会超时的,此时需要扭转思路,枚举k的x次方,x取值最多到60左右就可以了,因为每个数范围是-1e9到1e9,故区间和的下限是-1e14上限是1e14。然后就没什么难度了。注意特判1和-1的情况,下面给代码:
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<utility>
#include<map>
#include<vector>
#define maxn 100005
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
const double eps = 1e-5;
map<LL, int>m;
LL a[maxn], p[65];
int main(){
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
a[i] += a[i - 1];
}
m[0] = 1;
LL ans = 0;
if (k == 1){
for (int i = 1; i <= n; i++){
ans += m[a[i] - 1];
m[a[i]]++;
}
}
else if (k == -1){
for (int i = 1; i <= n; i++){
ans += m[a[i] - 1];
ans += m[a[i] + 1];
m[a[i]]++;
}
}
else{
p[0] = 1;
int pos = 1;
while (1){
p[pos] = p[pos - 1] * k;
if (p[pos] > 1e14 || p[pos] < -1e14)
break;
pos++;
}
for (int i = 1; i <= n; i++){
for (int j = 0; j < pos; j++){
ans += m[a[i] - p[j]];
}
m[a[i]]++;
}
}
printf("%lld\n", ans);
}