Codeforces Round #489 (Div. 2)
题目大意:求有多少个区间满足 区间的积/区间的和 = k
思路:我们很容易就能想到我们要在区间的积上做文章,因为如果数组里面每个数都>= 2那么 最多连乘不超过64次后面就不可能存在答案啦,
那么我们把连续的一段1缩成一个点,然后暴力枚举区间,直到区间的值大于一个数就退出循环, 里面的统计比较不好写,写挂了好几次。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 2e5 + 7; const int M = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, k, tot; LL a[N], b[N]; bool flag[N]; int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; i++) { scanf("%lld", &a[i]); } for(int i = 1; i <= n; i++) { if(a[i] > 1) b[++tot] = a[i]; else { int cnt = 0; while(i <= n && a[i] == 1) { i++; cnt++; } i--; b[++tot] = cnt; flag[tot] = true; } } LL ans = 0; LL up = 1e11; for(int i = 1; i <= tot; i++) { if(flag[i]) { if(k == 1) ans += b[i]; continue; } LL cnt1 = 0, cnt2, now = b[i], sum = b[i]; if(flag[i - 1]) cnt1 = b[i - 1]; if(k == 1) ans++; for(int j = i + 1; j <= tot; j++) { if(flag[j]) { cnt2 = b[j]; if(now % k == 0) { LL need = now / k, all = cnt1 + cnt2; if(need > sum) { need -= sum; all--, need--; if(need <= all) { ans += all - need + 1; if(cnt1 > need) ans -= cnt1 - need; if(cnt2 - 1 > need) ans -= cnt2 - 1 - need; } } } sum += b[j]; } else { now *= b[j]; sum += b[j]; if(now > up) break; if(now % k == 0) { LL ret = now / k; if(ret >= sum && ret - sum <= cnt1) { ans++; } } } } } printf("%lld\n", ans); return 0; } /* */