附上大佬博客:https://www.cnblogs.com/chenquanwei/p/9477822.html;
题意:找连续m个权值的和为k的非负次方的个数;
很容易想到用前缀和,计算所有前缀和然后找和为k的非负次方的个数就行了。但是找所有前缀和必然超时;
还是这种思路牛逼,计算每个数的前缀和s,然后找s-k^0, s-k^1, s-k^2....等等,如果能够找到的话,那么s和s-k^m的差值就是要求的k^m的值,而且2^53大概1e15,所以每个数的前缀和循环一边也不会超时;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
map<ll,ll>mp;
int main()
{
ll n,k;
scanf("%lld%lld",&n,&k);
mp.clear();
mp[0] = 1;
ll s = 0,a,ans = 0;
for(ll i = 0;i < n;i++){
scanf("%lld",&a);
s+=a;//计算每个数的前缀和;
if(k==1) ans+=mp[s-1];//找和为k^m的个数
else if(k==-1) ans+=mp[s-1]+mp[s+1];
else{
ll t = 1;
while(abs(t)<=1e15){//可能正可能负,绝对值最多不超过1e15
ans+=mp[s-t];
t*=k;
}
}
mp[s]++;
}
printf("%lld\n",ans);
return 0;
}