P7116 [NOIP2020] 微信步数

原题

简化题意:
有一个 k 维场地,第 i 维宽为 wi,即第 i 维的合法坐标为 1, 2, · · · ,wi。
小 C 有一个长为 n 的行动序列,第 i 元素为二元组 (ci, di),表示这次行动小 C 的坐标由 (x1, x2, . . . , xci, . . . , xk) 变为(x1, x2, . . . , xci + di, . . . , xk)。小 C 会将行动序列重复无限次,直到走出这个场地。
接下来,小 C 会以场地中的每个整点为起点,按照行动序列走直到走出场地。小 C 想知道他一共会走几步。
答案对1e9 + 7取模
n<=5e5,k<=10,wi<=1e9,di1,1

首先因为每一位是独立的,我们不妨把k维拆开

我们可以发现如果枚举每个位置并模拟走路过程复杂度必然爆炸,故此我们考虑改变记录答案的方式

我们考虑对于每个移动次数i多有少个起点走i步还没有走出去,如果没有会产生+1的贡献

我们不妨设i=k×n+j,我们只需要考虑j不同即可,因为在imodn的情况下每个数只有初始位置是不同的

定义sd表示走了一个周期(即走了一个循环)后这一维的变化量,premaxi,d表示d这一维走前i步时的前缀最小位移,premini,d表示d这一维走前i时的前缀最大位移

对于从xd开始走了k个完整周期又走了i步的第d维,要满足以下条件:

  • sd>0,我们可以发现走了i步后依然没有走出去的条件要求:

    1. xd+preminn,d1,意思是这个点的坐标在第一周期任何一步都>= 1,而又因为sd>0,所以在任意时间都>=1
    2. xd+sd×k+premaxi,dwi,意思是这个点的坐标在最后一个周期后走的i步内wi
    3. xd+sd×(k1)+premaxn,dwi,意思是这个点坐标在最后一个周期走完后位置wi,而又因为sd>0,所以在任意时间都wi
    • 合并后即为1premaxn,dxdwisd×kmax(premaxi,d,premaxn,dsd)
  • sd<0时,相同的,可以得到:1sd×kmin(premini,d,preminn,dsd)xdwipremaxn,d

  • 对于sd=0,可以得到:1preminn,dxdwipremaxn,d

我们可以发现我们在计算时已经枚举了i, d,所以在这个柿子中只有k为未知数

而且可以发现,k越大这个范围的区间肯定越小。因此对于每一维,我们可以通过二分的方法算出k最大的取值limd。但我们肯定不能直接暴力,不然复杂度会直接爆炸。这里怎么处理到后面再说

对于每一个k[0,limd],对答案的贡献即为d(rdld+1),其中ld,rd表示d这维的xd能取到的起点上下界。

根据前面的推到,rdld+1是一个关于k的一次函数,而若干个一次函数乘在一起,就形成了关于k的一个多项式,我们记作f(x)=d(rdld+1),因此答案=i=1min{limd}f(i),然后使用插值计算即可。

复杂度O(nk)

posted @   FOX_konata  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示