各种数论问题
欧拉定理
费马小定理
对于互质的两个数 \(a,p\),若 \(p\) 为质数,则有 \(a^{p-1}\equiv 1\pmod p\)。
欧拉定理
对于互质的两个数 \(a,p\),有 \(a^{\varphi(p)}\equiv 1\pmod p\)。
扩展欧拉定理
对于三个正整数 \(a,b,p\),有如下化简 \(a^b\) 的方式:
- 若 \(\gcd(a,m)=1\),则 \(a^b\equiv a^{b\bmod \varphi (m)}\pmod m\)。
- 否则,若 \(b\leq \varphi(m)\),则不再化简;否则 \(a^b\equiv a^{(b\bmod \varphi(m))+\varphi(m)}\pmod m\)。
CRT
考虑方程组
考虑对于每一个方程分别满足,且不影响其它方程组。对于方程组 \(i\),我们构造一个值 \(v_i\),使其模 \(j\neq i\) 的方程组余数均为 \(0\),模 \(n_i\) 余 \(a_i\)。不妨设 \(N=\prod n_i\),最终令 \(x=\sum v_i \bmod N\) 即可。
设 \(m_i=\frac{N}{n_i}\),根据取模操作对乘法的分配律,我们不难构造 \(v_i=a_im_im_i^{-1}\)。其中由于 \(m_i\bmod n_j=0\) 对任意 \(j\neq i\) 成立,且模 \(n_i\) 意义下 \(m_im_i^{-1} \bmod n_i=1\),故这样的 \(v_i\) 满足条件。
总时间复杂度 \(O(k^2\log n)\),瓶颈在于 \(O(N)\) 值域的快速幂会被计算 \(k\) 次,而 \(\log N=\log\prod n_i=\sum \log n_i=k\log n\)。
ExCRT
在模数 \(n_i\) 不互质时,求解同余方程组
考虑 \(k=2\) 时的情况:
它等价于:
即有 \(n_1k_1-n_2k_2=a_2-a_1\)。这个方程是一个二元一次不定方程,其中未知数是 \(k_1,k_2\)。使用 exgcd 构造出 \(k_1,k_2\) 的一组特解,也就可以求出 \(x\) 的一个特殊解 \(x_0\)。每一个 \(k_1\) 的变化量为 \(\frac{n_2}{\gcd(n_1,n_2)}\),也即每一个 \(x\) 的变化量为 \(\mathrm{lcm}(n_1,n_2)\),那么有通解 \(x=x_0+k\times \mathrm {lcm}(n_1,n_2)\),其中 \(k\) 是任意整数。则原线性同余方程组等价于:
若 \(k>2\),按上述规则将每个同余方程合并即可。复杂度是 \(k\log V\)。
Miller_rabin 素性测试
我们有如下两个素性检验依据:
费马素性检验:若存在 \(1\leq a<p\) 使得 \(a^{p-1}\bmod p\neq 1\),则 \(p\) 一定不是素数。
它的检验依据是费马小定理。但我们不能保证所有不满足上述条件的 \(p\) 都是素数。因此我们需要另一个依据。
二次探测定理:若 \(p\) 为奇素数,则 \(x^2\equiv 1\pmod p\) 的解为 \(x\equiv \pm 1\pmod p\)。
证明可以利用平方差公式。对于一个奇数 \(p\),我们可以得到一个测试流程:
- 选取一个底数 \(a\),初始化指数 \(d=p-1\),先利用费马素性检验判断 \(a^d\bmod p=1\) 是否成立。不成立则直接判断为合数。
- 注意到此时 \(a^d\bmod p=1\)。由于第二个性质需要利用平方,因此我们不断消去 \(d\) 中的 \(2\) 因子。也即每次令 \(d\gets \frac d2\),我们需要此时的 \(a^{d}\bmod p=\pm 1\) 成立。重复该操作直到 \(d\) 是奇数或计算出来的模数不等于 \(1\) 为止。若退出时,\(a^d\bmod p=\pm 1\),则该轮素性测试通过。
设选取的底数个数为 \(k\),则总复杂度 \(O(k\log^2 p)\)。我们一般选取前 \(12\) 个质数(\(2\sim 37\))作为底数进行判断。这样做在 \(2^{78}\) 以内的正确性都是有保证的。
int a[14]={0,2,3,5,7,11,13,17,19,23,29,31,37};
int mul(int x,int y,int p){
__int128 res=(__int128)x*y%p;
return (ll)res;
}
int quick_power(int base,int x,int p){
int res=1;
while(x){
if(x&1)res=mul(res,base,p);
base=mul(base,base,p);
x>>=1;
}
return res;
}
bool mr(int p){
if(p==2)return 1;
rep(i,1,12){
if(a[i]>=p)return 1;
if(quick_power(a[i],p-1,p)!=1)return 0;
int d=p-1;
bool ok=1;
while(!(d&1)){
d/=2;
int res=quick_power(a[i],d,p);
if(res!=1){
if(res!=p-1)ok=0;
break;
}
}
if(!ok)return 0;
}
return 1;
}
Pollard Rho 分解质因数
考虑对于一个合数 \(n\) 求它的一个非平凡因子。取出 \(n\) 的最小质因子 \(p\),利用函数 \(f(x)=(x^2+c)\bmod n\) 构造序列 \(x_1,x_2,\dots\),其中 \(x_1=0\),正整数 \(c\) 是随机值,\(x_i=f(x_{i-1})\)。我们可以认为这个映射是随机的。此时考虑另一个序列 \(y_1,y_2,\dots\),满足 \(y_1=x_i\bmod p\)。由生日悖论,我们知道这个映射首次出现环(也即 \(y_i=y_j\))的期望长度为 \(\sqrt p\)。当 \(y_i=y_j\) 时,\(x_i\equiv x_j\pmod p\),因此 \(\gcd(x_i-x_j,n)\) 是一个含有 \(p\) 这个因子的、\(n\) 的一个平凡因数。因此我们期望在 \(\sqrt p\) 项的时候,就找到一个 \(\gcd(x_i-x_j,n)\geq 1\),也即找到了一个 \(n\) 的非 \(1\) 因子。注意若求出来的值等于 \(n\),则需要重新随机 \(c\) 进行计算。
下面考虑如何判环:
- Floyd 判环:设 \(a=x_1,b=x_2\),每次更新 \(a=f(a),b=f(f(b))\),然后 check \(\gcd(a-b,n)\) 是否大于 \(1\) 即可。单次复杂度 \(O(\sqrt p\log n)\)。
- Brent 判环:相比于 Floyd 有一些常数优化。从 \(k=1\) 开始每一轮递增 \(k\),一轮中让 \(b\) 依次往前走 \(2^k\) 个位置,每走一步就 check \(\gcd(a-b,n)\) 是否大于 \(1\) 即可。
- 倍增优化:注意到 \(\gcd(a,n)>1\),则对于任意非负整数 \(b\) 都有 \(\gcd(ab\bmod n,n)>1\)。考虑维护 \(ab\bmod n\) 这个值(某一刻它等于 \(0\),则说明分解失败,需要重新随机),设定阀值 \(k\),每走 \(k\) 步后计算一次 \(\gcd\),则复杂度降低到 \(O(\sqrt p+k+\frac{\sqrt p\log n}{k})\),不妨取 \(k\) 和 \(\log n\) 大致同阶的值。具体实现时大多选取 \(k=128\)。
求得一个非平凡因子后,可以递归成两个部分进行进一步分解。每次分解之前需要使用 Miller-rabin 判断是否是素数。
mt19937_64 rd(time(0));
int getf(int x,int c,int p){
return (mul(x,x,p)+c)%p;
}
int plr(int n){
int a=0,b=0,c=rd()%(n-1)+1;
for(int w=1;;w*=2){
a=b;
int nwv=1;
rep(i,1,w){
b=getf(b,c,n),nwv=mul(nwv,abs(a-b),n);
if(i%128==0){
int res=__gcd(nwv,n);
if(res>1)return res;
}
}
int res=__gcd(nwv,n);
if(res>1)return res;
}
return n;
}
杜教筛
可以用来解决一类在亚线性复杂度下求 \(S(n)=\sum_{i=1}^nf(i)\) 的问题,其中 \(f(i)\) 是一个数论函数。
我们构造一个数论函数 \(g(i)\),有如下式子成立:
假如 \(f*g\) 的前缀和与 \(g\) 的前缀和都是好算的,则我们可以快速求出被减数,对减数进行整除分块后递归求解,即可求出 \(g(1)S(n)\) 的值。在记忆化的前提下,单纯这样计算的复杂度是 \(O(n^{\frac 34})\),若我们用线性筛预处理出前 \(O(n^{\frac 23})\) 个 \(S\) 的值,则可以将复杂度平衡到 \(O(n^{\frac 23})\)。
也即,我们的目标是,找到一个 \(g\),使得 \(g\) 的前缀和与 \(f*g\) 的前缀和都能很快地算出来。
筛 \(\mu\) 的前缀和
注意到 \(\mu * I=e\),不妨设 \(g=I\),则有 \(S(n)=1-\sum_{i=2}^nS(\lfloor\frac ni\rfloor)\)。直接上递归即可。
筛 \(\varphi\) 的前缀和
【法一】:使用杜教筛
根据 \((4)\),我们有 \(\varphi * I=id\),不妨设 \(g=I\),则有 \(g(1)S(n)=\sum_{i=1}^n i-\sum_{i=2}^nS(\lfloor\frac ni\rfloor)\)。直接上递归即可。
【法二】:利用莫比乌斯反演
用杜教筛筛出 \(\mu\) 的前缀和之后,利用整除分块即可。注意到整除分块的过程中,所有边界点都是某个 \(\lfloor \frac ni\rfloor\)(根据右端点的那个结论),故所有要用到的 \(S\) 都是筛 \(\mu\) 的时候用到过的,不会增加复杂度。
P3172 [CQOI2015] 选数
题意:给定 \(n,k,L,R\),求 \(\sum_{a_1=L}^R\sum_{a_2=L}^R\dots \sum_{a_n=L}^R [\gcd(a_1,a_2,\dots,a_n)=k]\),\(n,k,L,R\leq 10^9\)。
我们进行常规操作:
把除 \(k\) 看成整体进行整除分块,前面部分用杜教筛求即可。
P6055 [RC-02] GCD
题意:给出 \(N\),求:\(\sum_{i=1}^N\sum_{j=1}^N\sum_{p=1}^{\lfloor\frac{N}{j}\rfloor}\sum_{q=1}^{\lfloor\frac{N}{j}\rfloor}[\gcd(i,j)=1][\gcd(p,q)=1]\)。\(n\leq 2\times 10^9\)。
注意到 \(j\) 的部分很像在枚举 \(p,q\) 的 \(\gcd\),于是缩回去:
和上面那道题一样。做完了。
P3768 简单的数学题
题意:给定 \(n,p\),求 \(\sum_{i=1}^n\sum_{j=1}^n ij\gcd(i,j)\) 的值,对 \(p\) 取模。\(n\leq 10^{10}\)。
首先照例对原式用莫反化简,化简过程省略。
前面部分显然可以整除分块解决;后面部分,我们设 \(f(x)=\sum_{d\mid x}\mu(d)\frac{x^3}d\),则我们想要求 \(f(x)\) 的某些前缀和。尝试使用杜教筛,由于所有边界点都是某个 \(\lfloor \frac ni\rfloor\),所以对 \(n\) 做一次筛即可。下面对 \(f(x)\) 进行化简:
一般的 \(\varphi\) 的前缀和可以通过直接卷 \(I\) 解决。此处多带了一个 \(x^2\),我们可以利用 \(f(d)\times g(\frac xd)\) 的形式,卷上 \(id^2\),将 \(x^2\) 消成常数。于是设 \(g(x)=x^2\):
根据二次方和公式与三次方和公式,可以把杜教筛的复杂度做到 \(O(n^{\frac 23})\),这也是整个算法的瓶颈。
PN 筛
用来求一些复杂积性函数的前缀和。假设我们要求积性函数 \(f\) 的前缀和 \(F(n)=\sum_{i=1}^nf(i)\)。
Powerful Number
对于一个任意质因子次数都不小于 \(2\) 的数,我们称其为 Powerful Number。小于等于 \(n\) 的Powerful number 个数为 \(O(\sqrt n)\),可以通过枚举小于等于 \(\sqrt n\) 的质数以及其次数来搜索所有的 Powerful Number.
筛法
构造一个积性函数 \(g\) 满足对于任意质数 \(p\) 都有 \(g(p)=f(p)\),且 \(g\) 的前缀和好求。
找到函数 \(h(x)\) 使得 \(g*h=f\)。这个函数显然存在且 \(h\) 也是积性函数。因此 \(f(1)=g(1)=h(1)=1\)。对于一个素数 \(p\),我们有 \(f(p)=h(1)g(p)+h(p)g(1)=h(p)+g(p)\),根据上述限制得知 \(h(p)=0\)。根据积性函数定义,我们知道 \(h\) 仅在 PN 处取非 \(0\) 值。根据卷积我们可以作出如下推导:
我们只需要求出 \(h(p^c)\) 的值,即可通过积性函数性质在搜索过程中求出 \(\sqrt n\) 个有效位置的 \(h\)。求 \(h(p^c)\) 可以直接推理,也可以再次利用卷积形式进行推导:
于是可以递推求解。
注意到不超过 \(\sqrt n\) 的质数期望个数为 \(\frac{\sqrt n}{\log n}\),\(c\) 的级别不超过 \(O(\log n)\),因此求解 \(h(p^c)\) 有一个宽松的上界是 \(O(\sqrt n\log n)\)。搜索部分的复杂度为 \(O(\sqrt n)\),需要根据求 \(G\) 的复杂度计算总复杂度。注意若通过杜教筛求 \(G\),则根据单次求解杜教筛可以求出所有 \(\lfloor \frac ni\rfloor\) 的性质,总复杂度是 \(O(n^{\frac 23})\),也即瓶颈是杜教筛。
P5325 【模板】Min_25 筛
题意:定义积性函数 \(f(x)\),且 \(f(p ^ k) = p ^ k(p ^ k - 1)\)(\(p\) 是一个质数),求 \(\sum_{i = 1} ^ n f(i)\)。\(n\leq 10^{10}\)。
对于质数 \(p\),我们有 \(f(p)=p(p-1)\)。尝试构造 \(g(x)=x\varphi (x)\),不难发现 \(f(p)=g(p)\),\(g\) 是积性函数且 \(g(x)\) 的前缀和类似 P3768,可以通过卷上 \(id\) 做杜教筛解决。我们有如下推导:
\(h(p^c)\) 可以直接暴力求值,最后有 \(ans=\sum_{d=1,d 是 PN}^nh(d)G(\lfloor \frac nd\rfloor)\)。总复杂度 \(O(\sqrt n\log n+n^{\frac 23})\)。
Min25 筛
下面出现的所有 \(p\) 都表示质数。
对于一个积性函数 \(f(x)\),若我们能快速求出 \(f(p^k)\) 的值,且 \(f(p)\) 可以表示为项数较少的多项式,则可以使用该筛法在 \(O(\frac{n^{\frac 34}}{\log n})\) 的复杂度内求出 \(S(n)=\sum_{i=1}^nf(i)\)。上述“表示为项数较少的多项式”的意义是,它可以被拆成若干个完全积性函数的加和。
对所有质数求 \(f(p)\) 的和
我们把质数位置的 \(f(p)\) 拆成若干个完全积性函数相加,设某一个完全积性函数为 \(q(x)\),我们有对于任意的 \(p\),\(q(p)=f(p)\),
我们要求 \(g(n)=\sum_{p\le n}f(p)=\sum_{p\le n}q(p)\)。先使用线性筛求出 \(\sqrt n\) 内的质数,设共有 \(c\) 个,第 \(i\) 个记为 \(p_i\)。下文设 \(P\) 表示质数集,\(lpf(x)\) 表示 \(x\) 的最小质因子。
考虑 dp。设 \(g(n,j)=\sum_{i=1}^n[i\in P\ or\ lpf(i)>p_j]q(i)\),最终答案显然是 \(g(n,c)\),初始值为 \(g(x,0)\)(这是一个完全积性函数的前缀和,一般来说是好求的)。考虑从 \(g(n,i-1)\to g(n,i)\),我们要减去 \(lpf=p_{i}\) 的所有合数的贡献:
解释:由于 \(q\) 是完全积性函数,故可以任意把 \(p_j\) 这个因子提出来。后面减式里的第一个 \(g\) 表示除掉一个 \(p_j\) 后所有要被减去的合数(\(p_j\) 是最小的,故剩的不能小于 \(p_j\))和质数的贡献。注意到这部分有 \(\leq p_{j-1}\) 的质数也被计入,但是他们对应的 \(\times p_j\) 后得到的合数已经在之前被除去了,故这里不再除去,在后一个式子处补回来。
上述式子显然只会用到所有的 \(\lfloor \frac ni\rfloor\),共 \(\sqrt n\) 个。注意到所有的 \(p\) 都不超过 \(\sqrt n\),而所有 \(1\sim \sqrt n\) 的值都被 \(\lfloor \frac ni\rfloor\) 完全覆盖,故不用再额外考虑 \(p\) 的部分。使用整除分块找到所有 \(\sqrt n\),分值的大小分别对应到两个 \(\sqrt n\) 的数组里即可。该过程同时需要处理 \(g(x,0)=\sum_{i=1}^x q(i)\) 的值。
证明所有 \(1\sim \sqrt n\) 的值都被 \(\lfloor \frac ni\rfloor\) 完全覆盖,只需要证明 \(\frac n{\sqrt n}\sim \frac nn\) 之间两两差值不超过 \(1\)。这是反比例函数,取 \(\frac n{\sqrt n}\) 和 \(\frac n{\sqrt n+1}\) 即可,通分发现两者差值必定小于 \(1\),故得证。
利用 \(g\) 求 \(S(n)\)
下面的推导不需要利用完全积性函数的性质,因此提到的 \(f\) 函数就是原题中的 \(f\)。我们同样设 \(S(n,j)=\sum_{i=1}^n[lpf(i)>p_j]f(i)\),把贡献拆成质数和合数两部分,对合数枚举最小质因子以及次数:
前面的相减是计算的质数;后面的和式是合数部分。对于 \(e\neq 1\) 的情况,\(p_k^e\) 本身也是合数,没有其他因子时也要计入贡献,故最后要加上 \([e\neq 1]\)。按照 \(j\) 从大到小递归算即可,终点是 \(p_j\geq n\)。
上述两个式子经证明,都可以直接计算而不加任何前缀和、记忆化等优化,复杂度也正确。最终答案是 \(S(n,0)\)。
BSGS
给定 \(a,b,p\),求 \(a^x\equiv b\pmod p\) 的最小整数解,其中 \(a,p\) 互质。朴素的算法是 \(O(p)\) 的,只需要枚举 \(x\) 从 \(0\sim p-2\) 即可找到答案。
考虑根号优化。设 \(t=\lceil \sqrt p\rceil\),将 \(x\) 表示为 \(it-j\),其中 \(0\le j<t\)。显然 \(i\) 也在根号级别。于是有:
先枚举 \(b\times a^j\),共计 \(O(\sqrt p)\) 个,将这些数用一个哈希表标记。再枚举 \(i\),每次判断是否存在一个 \(j\) 使得左式等于右式,在哈希表里找即可。选择最小的一个 \(i\),总复杂度 \(O(\sqrt n)\)。
这里要求有互质,是因为还原回去等价于左右两边同时除了一个 \(a_j\),需要有逆元。
exBSGS
考虑 \(a,p\) 不互质的情况。注意上述过程需要 \(a\bmod p\) 有逆元,因为我们把除的一个数乘过去了。因此我们要把 \(a,p\) 做成互质的情况。具体地,我们考虑每次给方程同时除掉一个 \(a\) 和 \(p\) 的 \(\gcd\),直到 \(a\) 和 \(p\) 互质:
注意在整个过程中,若存在某一个时刻求出来的 \(d\) 不能整除 \(b\),则无解。此时移项过去,可以用 BSGS 求出最小的 \(x-k\) 的值。注意 \(k\) 很小,需要暴力枚举每一个 \(<k\) 的数判断是否有更小的解,且这部分是否有解与消 \(b\) 是否成功无关。
类欧几里得算法
给定 \(n,\,a,\,b,\,c\) ,分别求 \(f(n)=\sum\limits_{i=0}^{n}\lfloor \frac{ai+b}{c} \rfloor\),\(g(n)=\sum\limits_{i=0}^{n}{\lfloor \frac{ai+b}{c} \rfloor}^2\),\(h(n)= \sum\limits_{i=0}^{n}i\lfloor \frac{ai+b}{c} \rfloor\) 。
求解 \(f(n)\)
我们把函数写成 \(f(a,b,c,n)\) 的形式。首先对于 \(a,b\geq c\) 的情况,可以让 \(a,b\) 对 \(c\) 取模:
此时可以看作是 \(a,b<c\)。我们枚举后面那个下取整的值,并做下标偏移,舍去原来为空的 \(0\),新的 \(j\) 下标从 \(0\) 开始。继续进行化简:
下一步显然递归,并执行 \(c\gets c \bmod a\)。注意到把 \((a,c)\) 提出来之后,每一轮的变换等价于 \((a,c)\to (c\bmod a,a)\),在 \(a=0\) 时停止递归,等价于辗转相除,复杂度 \(O(\log n)\)。
求解 \(g(n)\)
首先还是先取模:
考虑 \(a<c,b<c\) 的情况。下面换元,令 \(m=\lfloor\frac{an+b}c\rfloor\),\(t=\lfloor \frac{jc+c-b-1}{a}\rfloor\)。
求解 \(h(n)\)
取模:
仍然做同样的换元:
需要同时求 \(f,g,h\) 的时候,注意到所有函数的递归对象除自己外都是一致的。所以可以把 \(f,g,h\) 封在同一个结构体里,每次递归同时把三个都求出来。因此总复杂度 \(O(\log V)\)。
[ARC111E] Simple Math 3
题意:\(T\) 次询问,每次给定 \(4\) 个整数 \(A,B,C,D\),求有多少个正整数 \(i\) 满足闭区间 \([A+Bi,A+Ci]\) 中没有 \(D\) 的整倍数。\(T\leqslant10^4,1\leqslant A\lt D,0\leqslant B\lt C\lt D,2\leqslant D\leqslant 10^8\)。
没有 \(D\) 的整倍数的一个必要条件是 \((C-B)i<D\),化简得到 \(i\le \lfloor\frac{D-1}{C-B}\rfloor\)。此时,仍不合法的区间里至多有 \(1\) 个 \(D\) 的倍数。于是考虑容斥统计不合法的 \(i\) 的数目,它等价于所有区间里 \(D\) 的倍数的个数。差分可以求出一个区间里 \(D\) 的倍数的数量,于是有:
后面的求和式子是两个类欧。注意下标转化成从 \(i=0\) 开始。
[ABC283Ex] Popcount Sum
题意:\(T\) 组询问,每组询问给定 \(n, m, r\),请求出 \(\sum_{i\bmod m = r}^n \text{popcount}(i)\)。\(1\le T \le 10^5,\ 1\le m \le n \le 10^9,\ 0\le r < m\)。
考虑拆位表示 popcount:
考虑枚举原题中 \(\lfloor \frac im\rfloor\) 的值:
外层暴力枚举,内层类欧做即可。复杂度 \(O(T\log V^2)\)。
[ARC166E] Fizz Buzz Difference
题意:给定 \(n,a,b\),求 \(L,R\) 使得区间 \([L,R]\) 中 \(a\) 的倍数个数比 \(b\) 的倍数个数恰好多 \(n\) 个。求出 \(R-L\) 最大的一组解,相同则输出 \(L\) 最小的一组解。多测,$1\le T\le 2\times 10^5,1\le n\le10^6,1\le a\lt b\le 10^6 $。
注意到由于 \(b>a\),因此我们在最大化 \(R-L\) 的前提下,区间内两数倍数的出现次数之差一定越大越好。因此我们可以把限制设成 \(a\) 的倍数比 \(b\) 的倍数最多多 \(n\) 个。
首先找到一个合法区间 \([L,R]\) 的必要条件:\(L-1\) 和 \(R+1\) 均是 \(a\) 的倍数。若不是,则可以在不使答案更劣的前提下继续延长区间。不妨设 \(L-1=ax\),\(R+1=ay\)。
其次,我们希望尽可能多地装 \(b\),因此我们希望首个 \(b\) 尽可能靠前。因此我们可以找到一个合法区间的充分条件:大于等于 \(L\) 的下一个 \(b=ax+\gcd(a,b)\)。这显然是最靠前的一个 \(b\) 的位置。于是可以计算出满足该前提的区间内 \(b\) 的个数为:\(\frac{ay-1-ax-\gcd(a,b)}{b}+1\)。于是我们有如下式子需要满足:
注意到 \(y-x\) 每次增大 \(1\) 时,被减数立即增大 \(1\),而减数平均每次增加 \(\frac{a}b\),虽然有突变,但被减数是均匀增加,且突变值显然不超过间隔次数,故左式有单调性,二分即可求得最大的 \(y-x\),也即最大的 \(R-L\)。
下面设 \(y-x=t\)。此时需要找到最小的 \(x\) 使得 \([ax+1,a(x+t)-1]\) 合法。注意这里沿用 \(x\) 的原因是 \(L-1=ax\),\(R+1=ay\) 为区间合法的必要条件。
\([ax+1,a(x+t)-1]\) 中 \(b\) 的个数为 \(\lfloor\frac{a(x+t)-1}{b}\rfloor-\lfloor\frac{ax}{b}\rfloor\)。由于所有区间内 \(b\) 的取值个数的极差不超过 \(1\),故不合法时,\(b\) 的个数为 \((\lfloor\frac{at-\gcd(a,b)-1}{b}\rfloor+1)-1\),我们希望找到首个合法的位置。考虑我们对每一个 \(x\) 对应的 \(b\) 的个数作前缀和累加,设 \(f(x)=\sum_{i=0}^x\lfloor\frac{ai+at-1}{b}\rfloor-\lfloor\frac{ai}{b}\rfloor\),我们只需要找到首个 \(x\) 使得 \(f(x)>(x+1)\times (\lfloor\frac{at-\gcd(a,b)-1}{b}\rfloor)\) 即可,因为一个最小的合法 \(x\),一定是首个对应合法 \(b\) 的数量大于 \(\lfloor\frac{at-\gcd(a,b)-1}{b}\rfloor\) 的位置,又因为所有 \(x\) 对应的数量都不可能小于这个值,所以找到首个前缀个数和大于最低线的位置即可。
不难发现一个位置大于了,之后的所有位置都满足大于的条件,故同样可以二分解决,需要快速计算:
类欧即可。总复杂度 \(O(T\log^2n)\)。
万能欧几里得
对于直线 \(y=\frac{ax+b}{c}\),求其下方所有整点的数量。考虑从左到右遍历题目中直线的定义域 \((0,n]\),我们需要统计所有横坐标为 \([1,n]\) 的整点数量。定义矩阵 \(U,R\),在直线向上穿过水平整坐标直线时,给答案向量成上一个 \(U\), 在直线向右穿过竖直整坐标直线时,给答案向量成上一个 \(R\),根据题目要求构造即可。现在实现函数 \(f(a,b,c,n,U,R)\) 表示求上述限制下的答案矩阵。我们限制整点时,先执行 \(U\),后执行 \(R\),则第 \(x\) 个 \(R\) 之前的 \(U\) 的数目为 \(\lfloor \frac{ax+b}{c}\rfloor\)。
考虑递归求解。当 \(a\geq c\) 时,每个 \(R\) 前面都至少有 \(\lfloor\frac ac \rfloor\) 个 \(U\),于是可以化简,递归到 \(f(a\bmod c,b,c,n,U,U^{\lfloor\frac ac \rfloor}\times R)\) 。
当 \(a<c\) 时,斜率小于 \(1\),我们将直线按照 \(y=x\) 作轴对称,此时斜率重新 \(>1\),可以继续递归。考虑变化:此时 \(R\) 和 \(U\) 互换,斜率变为倒数,令 \(m=\frac{an+b}{c}\) 表示原来的 \(U\) 的个数,分析第 \(y\) 个 \(U\) 前面的 \(R\) 的个数,即最大整数 \(x\) 满足 \(y>\lfloor \frac{ax+b}{c}\rfloor\),化简可得 \(x\le \lfloor \frac{cy-b-1}{a}\rfloor\)。
注意到此时存在两个问题:截距为负且直线定义域上不以新 \(R\) 结尾。分别考虑解决:
- 对于第一个问题,我们将直线往左平移一位,此时 \((-1,0]\) 的贡献暴力计算。这一段里有 \(\lfloor\frac{c-b-1}{a}\rfloor\) 个原来的 \(R\) 和一个原来的 \(U\),需要乘在递归函数的前面。
- 对于第二个问题,我们抹去 \(m\) 后的尾巴。式子类似。