题意:给出一个有n个数的序列,还有一个k,问在这个序列中有多少个子序列使得sum[l, r] = k^0,1,2,3……
思路:sum[l, r] = k ^ t, 前缀和sum[r] = sum[l-1] + k^t。即如果后面有一段序列使得sum[l,r] = k^t,那么它可以转化为前缀和相减使得这一段大小为k^t,即sum[i] = sum[j] + k^t (1 <= j < i)。
那么对于处理好的每一个前缀和,直接往后面加上k^t(0<=t<=x,k^x是不超过题目范围的数)。然后在后面遍历的时候直接加上对应那个数的权值。
因为数据很大,所以只能用map来装权值。
代码实现:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll f[101005]; 5 ll k_t[1000]; 6 int main() 7 { 8 int n,k,i,j,cnt; 9 while(cin>>n>>k) 10 { 11 map<ll,int>mp; 12 memset(f,0,sizeof(f)); 13 memset(k_t,0,sizeof(k_t)); 14 for(i=1;i<=n;i++) 15 { 16 cin>>f[i]; 17 f[i]+=f[i-1]; 18 } 19 k_t[1]=1;cnt=2; 20 if(k==-1)k_t[2]=-1,cnt++; 21 else if(k!=1) 22 { 23 ll temp=k; 24 while(temp<1e15) 25 { 26 k_t[cnt++]=temp; 27 temp*=k; 28 } 29 } 30 ll ans=0; 31 for(i=1;i<cnt;i++)mp[k_t[i]]=1; 32 for(i=1;i<=n;i++) 33 { 34 if(mp[f[i]])ans+=mp[f[i]]; 35 for(j=1;j<cnt;j++) 36 mp[f[i]+k_t[j]]++; 37 } 38 cout<<ans<<endl; 39 } 40 return 0; 41 }