http://codeforces.com/contest/776/problem/C
一开始做的时候,就发现是预处理前缀和,然后对于每一个前缀和,如果他能成为一个贡献,就是能和前面的某些段
组合成和为k^x的话,那么需要cur_per_sum - val = k^x,这样可以解出val是多少,去前面找有多少个数是val就行了。
然后开始的时候我是先把所有数字都预处理然后放入map的,这样的做法是不对的,变得十分麻烦,
可能前面的前缀和是0,然后后面的前缀和也是0,但是当前枚举的这一位不能和后面的组合,这样就会GG。
所以可以枚举cur的时候,把cur - 1的东西放入去先,这样就不会被后面的影响。
记得特判1和-1的情况,特别是-1
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> const int maxn = 1e5 + 20; map<LL, int>mipos; map<LL, int>num; const LL uppos = 1e14; const LL upnag = -1e14; LL sum; LL mypow(LL k, LL b) { LL ans = 1; for (int i = 1; i <= b; ++i) { ans *= k; } return ans; } void work() { int n; LL k; cin >> n >> k; num[0] = 1; LL ans = 0; for (int i = 1; i <= n; ++i) { int x; cin >> x; sum += x; int sel = 0; for (int j = 0; ; ++j) { LL now = mypow(k, j); if (now > uppos) break; if (now < upnag) break; ans += num[sum - now]; sel++; if (k == 1) break; if (k == -1 && sel == 2) break; } num[sum]++; } cout << ans << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif IOS; work(); return 0; }