4307. 【NOIP2015模拟11.3晚】喝喝喝

题目描述
  • 有一个长度为n的序列a
  • 定义一个坏对{ax,ay}当且仅当 x &lt; y x&lt;y x<y a [ x ] m o d &ThinSpace;&ThinSpace; a [ y ] = k a[x] \mod a[y]=k a[x]moda[y]=k
  • 求有多少个连续子序列不包含坏对
  • 1 ≤ n , k , a i ≤ 1 0 5 1 \le n,k,a_i \le 10^5 1n,k,ai105
题目分析

题目可以抽象成:
有一些区间不能被包含,求合法的区间数。

于是我们在找完区间之后,可以随便搞搞(方法有很多)
比如先算出不合法的区间数,然后再用总数减去它得出答案(具体的自己想)

关键在于怎么找区间,这个方法更多。

方法一:

我们知道,如果 a [ x ] m o d &ThinSpace;&ThinSpace; a [ y ] = k a[x] \mod a[y]=k a[x]moda[y]=k,则 a [ y ] ∣ a [ x ] − k a[y] \mid a[x]-k a[y]a[x]k
因此我们可以直接倒着搜,搜到a[i]时我们看其减去k后的约数(当然是要大于k的),然后用一个桶存一下,加起来就行了。
时间复杂度:O( n a i n \sqrt{a_i} nai )

方法二:

我们其实有更快(一点)的方法。
因为在线求约数实在是太浪费时间了,于是我们可以直接离线预处理。
从1到100000枚举他们的倍数,然后就发现时间是O( n log ⁡ 2 n n \log_2n nlog2n)
于是其实就只有 n log ⁡ 2 n n \log_2n nlog2n对约数,于是总时间复杂度就是O( n log ⁡ 2 n n \log_2n nlog2n)

当然还有其它的方法,在这里就不说了(相信大家的脑洞都很

代码(无)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值