子序列肯定不可能是无限长的
由于amax=1e8 nmax=2e5 kmax=1e5
则summax=1e82e51e5=2e18 而longlong刚好能hold住
那也就是说一个子序列里面非1的个数不超过64个(longlong范围是2^64)
那我们可以把连续的1缩成一坨 然后枚举每个点 暴力地往后找
具体的实现:记le[i]记录每个数左边第一个不是1的数在哪儿 然后用类似链表的方法遍历 如果乘积马上就要爆longlong了 就马上break
这样复杂度O(64*n)
#include<bits/stdc++.h>
#define N 200005
#define ll long long
using namespace std;
template<class T>
inline void read(T &x)
{
x=0;
static char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
int n,le[N],ans;
ll k,a[N];
inline bool Overflow(ll mul,ll x)
{
if(mul>LLONG_MAX/x) return true;
return false;
}
int main()
{
read(n); read(k);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++)
{
if(a[i-1]!=1) le[i]=i-1;
else le[i]=le[i-1]; //记录每个数左边第一个不是1的数在哪儿
}
for(int i=1;i<=n;i++)
{
ll sum=a[i],mul=a[i];
if(mul==sum*k) ans++;
for(int pre=i,now=le[i];;pre=now,now=le[now])
{
ll del=mul-sum*k;
if(del>0&&del%k==0&&del/k<pre-now) ans++; //判断跳过的这段1 能否更新答案
if(!now||Overflow(mul,a[now])) break;
mul*=a[now]; sum+=a[now]+(pre-now-1);
if(mul==sum*k) ans++;
}
}
cout<<ans<<endl;;
return 0;
}