新数论分块的推广及其复杂度证明 【数论】【分块】

事情是这样的。。。
最近校内集训有这样一道题:

给定一个N(N<1e12),问有多少个M使得 (N%M)|M.

校内绝大部分的人(其实就是除了我外)都是用质因数分解过的,大概是:

因为gcd(n,m)=gcd(n%m,m),gcd(n%m,m)==n%m (题意),所以就有gcd(n,m)=n%m.
枚举a=n%m,则要n=ax,m=ay 满足 gcd(x,y)=1.
又因为m|n-a (n-n%m),两边除以a,有y|x-1,此时显然有gcd(x,y)=1,所以上面的限制可以直接忽略。
那么再统计x-1的因数个数即可。

复杂度大约为N的所有约数的约数个数,有点绕...

这种做法太暴力且复杂度玄学,但这做法竟然跑得飞快。。。
于是我抱着一股愤怒的心情写下这篇博客,来推广一下新数论分块。

------------------------------------------------------我是萌萌哒的分割线--------------------------------------------------------

这其实是一道新数论分块(暂且叫它这个名字)的板子题。

先说结论:
类似于数论分块中, ⌊ n i ⌋ \lfloor \frac{n}{i}\rfloor in的有有效取值只有 O ( n ) O(\sqrt n) O(n )个, ( ⌊ n i ⌋ , ⌈ i n % i ⌉ ) (\lfloor \frac{n}{i}\rfloor,\lceil\frac{i}{n\%i}\rceil) (in,n%ii)的有效取值只有 O ( n ln ⁡ n ) O(\sqrt n \ln n) O(n lnn)个。
( i ∣ n i|n in时单独划一组,显然这最多不超过 O ( n ) O(\sqrt n) O(n )组)
(上述的取整都可以分别改成上取整和下取整,这见仁见智)

推导过程如下:
令 a = ⌊ n i ⌋ , b = ⌈ i n % i ⌉ 令a=\lfloor \frac{n}{i}\rfloor,b=\lceil\frac{i}{n\%i}\rceil a=in,b=n%ii,并假定存在一个常数S.
那么对于同一个a而言:
1.若 b ≤ S b\leq S bS时,则 ( a , b ) (a,b) (a,b)最多有S组。
2.若 b > S b> S b>S时:
首先有 ⌊ n i ⌋ = a ⇔ n i ≥ a ⇔ i ≤ n a \lfloor \frac{n}{i}\rfloor=a \Leftrightarrow \frac{n}{i}\geq a \Leftrightarrow i \leq \frac{n}{a} in=ainaian
其次有 ⌈ i n % i ⌉ = ⌈ i n − a i ⌉ > S ⇒ ⌊ i n − a i ⌋ ≥ S ⇔ i n − a i ≥ S ⇔ i ≥ S ⋅ ( n − a i ) ⇔ i ≥ S n a S + 1 = n a + 1 S \lceil\frac{i}{n\%i}\rceil=\lceil\frac{i}{n-ai}\rceil > S \Rightarrow \lfloor\frac{i}{n-ai}\rfloor \geq S \Leftrightarrow \frac{i}{n-ai} \geq S \Leftrightarrow i \geq S\cdot(n-ai) \Leftrightarrow i \geq \frac{Sn}{aS+1}=\frac{n}{a+\frac{1}{S}} n%ii=naii>SnaiiSnaiiSiS(nai)iaS+1Sn=a+S1n
n a ≤ i ≤ n a + 1 S \frac{n}{a}\leq i\leq \frac{n}{a+\frac{1}{S}} ania+S1n,显然 i i i的整数取值最多只有 n a + 1 S − n a = n a + a 2 S ≤ n a 2 S \frac{n}{a+\frac{1}{S}}-\frac{n}{a}=\frac{n}{a+a^2S}\leq\frac{n}{a^2S} a+S1nan=a+a2Sna2Sn

综合1和2,取 S = n a S=\frac{\sqrt{n}}{a} S=an ,则有 S + n a 2 S = O ( n a ) S+\frac{n}{a^2S}=O(\frac{\sqrt{n}}{a}) S+a2Sn=O(an )

则不同的a值的总贡献大约为 ∑ a = 1 n O ( n a ) = O ( ∑ a = 1 n n a ) = O ( n ⋅ ∑ a = 1 n 1 a ) = O ( n ln ⁡ n ) \sum_{a=1}^{n}O(\frac{\sqrt{n}}{a})=O(\sum_{a=1}^{n}\frac{\sqrt{n}}{a})=O(\sqrt{n}\cdot\sum_{a=1}^{n}\frac{1}{a})=O(\sqrt n\ln n) a=1nO(an )=O(a=1nan )=O(n a=1na1)=O(n lnn)
而实际上程序跑出来的界也十分接近 n ln ⁡ n \sqrt n\ln n n lnn

回到这题,其实就是问有多少个 M M M使得 M N % M = ⌈ M N % M ⌉ \frac{M}{N\%M}=\lceil \frac{M}{N\%M} \rceil N%MM=N%MM,直接套用上面的分块即可。
同时也可以证明答案不会超过 N ln ⁡ N \sqrt N\ln N N lnN然而这给直接质因数分解提供了很好的复杂度证明.

-------------------------------------------------------我还是萌萌哒的分割线--------------------------------------------------------
具体写法:
先按数论整除分块,确定出 [ i , j ] , ( ∀ x ∈ [ i , j ] , ⌊ n x ⌋ = a ( 常 数 ) ) [i,j],(\forall x \in[i,j],\lfloor \frac{n}{x}\rfloor=a(常数)) [i,j](x[i,j],xn=a())

观察到 ∀ x ∈ [ i , j ] , ⌈ x n % x ⌉ = ⌈ x n − a x ⌉ \forall x \in[i,j],\lceil\frac{x}{n\%x}\rceil=\lceil\frac{x}{n-ax}\rceil x[i,j],n%xx=naxx是一个不减的函数。
所以对于一个 l l l(令 ⌈ l n % l ⌉ = ⌈ l n − a l ⌉ = b \lceil\frac{l}{n\%l}\rceil=\lceil\frac{l}{n-al}\rceil=b n%ll=nall=b),要确定一个最大 r r r使得 [ l , r ] , ∀ x ∈ [ l , r ] , ⌈ x n − a x ⌉ = b ( 常 数 ) [l,r],\forall x \in[l,r],\lceil\frac{x}{n-ax}\rceil=b(常数) [l,r]x[l,r],naxx=b(),
即要找到最大的一个 r r r使得 ⌈ r n − a r ⌉ ≤ b \lceil\frac{r}{n-ar}\rceil\leq b narrb

那么剩下就是简单地推一下公式了:
⌈ r n − a r ⌉ ≤ b ⇔ r n − a r ≤ b ⇔ r ≤ b ⋅ ( n − a r ) ⇔ r ≤ b n a b + 1 \lceil\frac{r}{n-ar}\rceil\leq b \Leftrightarrow \frac{r}{n-ar} \leq b \Leftrightarrow r\leq b\cdot(n-ar) \Leftrightarrow r\leq \frac{bn}{ab+1} narrbnarrbrb(nar)rab+1bn
r = ⌊ b n a b + 1 ⌋ r=\lfloor \frac{bn}{ab+1} \rfloor r=ab+1bn

注意 x ∣ n x|n xn的情况要特判.

for (LL i=1,a,j;i<=n;i=j+1)	{
	j=n/(a=n/i);
	for (LL l=1,b,r;l<=j;l=r+1)	{
		if (n%l==0)	{
			assert(l==j);//当x|n时一定出现在整除分块的末尾处。
			//....
		} else	{
			b=l/(n%l);
			r=b*n/(a*b+1);
			//.....
		}
	}
}

你可能感兴趣的:(ACM笔记)