参考了别人的博客,已注明为转载
这也是看了题解搞定的,这题很巧妙的利用了范围的问题,我们先略过所有是1的数,(a1 + .... + an) *k 这个的最大范围是 n*k*1e8 = 2e18,接近LL_MAX 的范围,那也就是说,对于至少为2的数来说,64个数相乘就能爆掉这个答案,因此答案连续的段去掉1之后,至多只可能有64个数,那么再考虑1,因为1对乘积没有影响,因此我们可以把连续的1看成是1段,然后判断通过对和加上这些1里面的部分数,能不能有符合答案的数,然后跳过这段1,这样保证在计算一段的时候,只计算至多64次
然后碰到的坑,LL 类型爆了貌似不会立刻小于0 ?特判是否爆LL 用
if (mul > LLONG_MAX / a[j]) break;
然后没啥了,代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b){if (b == 0) return a; return gcd(b , a%b);}
LL lcm(LL a,LL b){ return a/gcd(a,b)*b;}
inline int read(){
int f = 1, x = 0;char ch = getchar();
while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
const int maxn = 2e5 + 10;
LL a[maxn],cnt[maxn];
int main(){
int n,k;
LL ans = 0;
n = read(); k = read();
for (int i=0; i<n; i++)
a[i] = read();
LL mul = 1,add = 0;
for (int i=n-1; i>=1; i--) {
if (a[i] == 1) cnt[i-1] = cnt[i] + 1;
}
for (int i=0; i<n; i++) {
mul = 1; add = 0;
for (int j=i; j<n; j++) {
if (mul > LLONG_MAX / a[j]) break;
mul *= a[j];
add += a[j];
if (mul == add*k) { ans++; }
else{
if (add*k < mul && mul % k == 0 && add + cnt[j] >= mul/k)
ans++;
LL x = cnt[j];
j += x;
add += x;
}
}
}
cout << ans << endl;
return 0;
}