之前有个题是类欧求 floor sum,感觉素质不是很高。
后来又有个题是万欧,这下这下了。
考虑这样一个事情:我们有一个 向量 \(v\),考虑有一条线段 \(y=\frac{ax+b}{c}\),其中 \(a,b,c\) 均为自然数且 \(c\gt 0\),定义域为 \((0,n]\)。
注意是右闭左开的。
这条线段随着 \(x\) 的增加,当碰到 \(x=k\) 的整线的时候,我们就对 \(v\) 做一次线性变换:\(v:=vR\);当碰到 \(y=k\) 的整线的时候,就对 \(v\) 做一次 \(v:=vU\) 的线性变换;如果是整点,则先做 \(U\) 后做 \(R\)。然后我们需要求出最后的 \(v\)。
显然我们最后只需要求出那个线性变换矩阵,设为 \(T\),然后 \(vT\) 就是答案。
为什么会发明出来这么奇怪的东西?其实有一个实际背景就容易理解了:我们可能维护的是一个变量 \(a\),这个 \(a\) 有一个变化规律,而我们要求 \(a\) 在某些时刻的和。
那么可以尝试构造一条线段:使得它碰到 \(y=k\) 的时候恰好就是 \(a\) 这个变量更新的时刻,然后线性变换 \(U\) 就等价于对变量 \(a\) 更新;当碰到 \(x=k\) 的时候恰好就是把 \(a\) 的当前值累加进答案的时刻,那么线性变换 \(R\) 就等价于 \(sum:=sum+a\) 这样的东西。
由于我们只关心 \((n,a,b,c,U,R)\),所以把这个六元组记作状态。
可以看出,一个 corner case 是 \(n=0\),此时 \(T=I\)。
可以看出,我们把整条线段上下平移整数格,不会改变结果,因此可以认为 \(b\in [0,c)\)。
当 \(a\ge c\) 的时候,考察 \((n,a,b,c,U,R)\) 和 \((n,a\bmod c,b,c,U,R)\) 两条线段的结果有什么区别,可以发现每一个 \(R\) 的前面都恰好多了 \(\lfloor \frac{a}{c} \rfloor\) 个 \(U\),所以可以重定义 \(R:=U^{\lfloor \frac{a}{c}\rfloor}R\) 然后变成 \(a\lt c\) 的情况。
当 \(a\lt c\) 的时候,感觉不是正常人能想到的角度。
注意到上面的线段对应这样一个东西:第 \(i\) 次 \(R\) 变换前共做了 \(\lfloor \frac{ai+b}{c} \rfloor\) 次 \(U\) 变换,记这个值为 \(s_i\)。
则其实就是:做 \(s_1\) 次 \(U\) 变换后做 \(R\) 变换,然后做 \(s_2-s_1\) 次 \(U\) 变换后再做 \(R\) 变换,然后做 \(s_3-s_1\) 次变换后再做 \(R\) 变换...,做 \(s_n-s_{n-1}\) 次变换后再做 \(R\) 变换。
注意到任何一个状态其实都和 \((s_1,s_2,...,s_n)\) 这个序列形成一一对应。
换个视角:第 \(i\) 次 \(U\) 变换前做了几次 \(R\) 变换!?
如果第 \(j\) 次 \(R\) 变换在第 \(i\) 次 \(U\) 变换前,则意味着:
如果我们拿一条 \(y=\frac{cx-b-1}{a}\) 的线段,然后交换一下 \(U,R\),好像两者就等价了。
当然这个只是大体思路,我们会发现有很多锅,最直接的:我们这里 \(-b-1\) 是个负数啊,第二个:新的 \(n\) 取值是多少,第三个:如果最后一个 \(U\) 后面还有 \(R\) 咋办。
首先解决第三个问题,由于 \(m=\lfloor \frac{an+b}{c} \rfloor\) 是原线段最后一次执行 U 变换的位置,所以第 \(m\) 次 \(U\) 变换之后的 \(R\) 都不会被统计进去,我们知道第 \(m\) 次 \(U\) 变换之前的 \(R\) 变换次数是 \(\lfloor \frac{cm-b-1}{a}\rfloor\),所以最后额外乘上 \(R^{n-\lfloor \frac{cm-b-1}{a} \rfloor}\) 作为修正即可。
然后第二个问题也得到了解决:算到 \(m\) 就够了捏。
第一个问题比较谔谔,注意到 \(c\gt b\),所以不妨把它变成 \(\frac{cx + (c-b-1)}{a}\),然后就从 \((0,m]\) 变成了算 \((0,m-1]\),这样就行了。
此时看似三个问题都解决了,但是我们缺的 \((0,1]\) 这块的线性变换谁给我补啊?
发现这个特判是容易的,在递归的开头乘上 \(R^{\lfloor \frac{c-b-1}{a} \rfloor}\times U\) 即可,也就是把第一个 \(U\) 和它之前的 \(R\) 拿出来特殊算(注意上一个特判是挂在递归结束后面的)。
设一次矩阵乘法的复杂度是 \(O(T)\) 则复杂度看上去是 \(O(T\log^2\max\{n,c\})\) 的,但是通过一些分析可以发现其实是 \(O(T\log\max\{n,c\})\) 的,因为每次的那个 \(\log\) 是 \(\log a-\log c\) 这样的
而且发现其实不一定是矩阵乘法(线性变换),只要有结合律就能捣鼓一下了啊。还能解决我们类欧的所有问题,因为类欧就是每个 \(x=k\) 的直线的整点个数,所以维护一个变量 \(cnt\),碰到 \(U\) 的时候修改,\(R\) 的时候累加进答案,那就是矩阵的形式。
例题:
CF868G El Toll Caves
这个题和万欧能有什么关系......
考虑策略肯定是让问的尽可能地均匀,然后可以列出方程 \(f_{i} = f_{i-k}+1(i\gt k)\) 以及 \(f_{i} = 1+\frac{1}{2}f_{i-k+n}(i\le k)\)。
对于第一类也就是考虑把所有答案在 \(i\) 的情况和答案在 \(i-k\) 的情况形成一一对应;第二类也是一个思想,不过由于 \(i\) 的第一次比 \(i-k+n\) 的第一次出现的早所以需要把第一次就问出来的特殊算掉。
可以发现这就是 \(i\rightarrow i+k\) 连边的那种形式,以 \(f_1\) 为未知数一直进行下去,可以得到关于 \(f_1\) 的一个一元一次方程,以及一个关于 \(f_1\) 的一次函数,表示这个环上的所有答案。
发现其它环上的过程一模一样,更准确地由于 \(n,k\) 同时乘除一个数答案不变,所以可以令 \(\gcd(n,k)=1\)。
那么从 \(1\) 一直开始走就只有一个大小为 \(n\) 的大环。
这样很显然是 \(O(n)\) 了,看起来非常牛逼,结果还是寄。
如果我们只有第一种转移那其实是很简单的,因为我们维护的两个东西:关于 \(f_1\) 的一次式 \(A(x)\)(最后有 \(f_1=A(f_1)\))以及答案关于 \(f_1\) 的一次式 \(B(x)\) 每多加一个人都是做了一次确定的变换 \(T\)(注意一次函数的复合还是一次函数,且这个过程有结合律)。那 \(T^n\) 直接快速幂就能求。
考虑第二种转移其实可以拆开来变成两次变换:一次 \(\times \frac{1}{2}\),一次是正常的变换。
两种变换的过程可以对应万欧构造的东西:把 R 变换设为第一种转移的变换,把 U 变换设为第二种转移里先做的那个 \(\times \frac{1}{2}\) 的变换,发现取 \(y=\frac{kx}{n}\) 这条直线就恰好满足要求。
时间复杂度 \(O(T\log)\)。