【CF992D】Nastya and a Game(思维好题)

子序列肯定不可能是无限长的

由于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; 
}

转载于:https://www.cnblogs.com/Patrickpwq/articles/9846540.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值