数论 —— 整除分块,常见经典例题。

什么是整除分块?

在我们求 ⌊ n i ⌋ \lfloor \frac n i \rfloor in 时会发现,当 i i i 不同时 ⌊ n i ⌋ \lfloor \frac n i \rfloor in 却可能相同。

i123456789101112131415
15 i \frac {15} {i} i151574332211111111

如果我们要求 ∑ i = 1 15 15 i \sum_{i=1}^{15} \frac{15}{i} i=115i15,如果直接枚举 i,那么时间复杂度是 O(n) 的。

而如上图所示,存在相邻的若干项的值是相同的,我们是否可以每次把相同值的区间算出来,用 区间长度 * 区间中的值 便是这段区间中所有值之和了。
这样就不需要遍历区间中重复值的位置,而 ⌊ n i ⌋ \lfloor \frac n i \rfloor in 中不同值有 2 n 2\sqrt n 2n 种,故复杂度降为 O ( n ) O(\sqrt n) O(n )

证明:
对于 i ≤ ⌊ n ⌋ , ⌊ n i ⌋ i \leq\lfloor\sqrt{n}\rfloor ,\left\lfloor\frac{n}{i}\right\rfloor in in 最多有 ⌊ n ⌋ \lfloor\sqrt{n}\rfloor n 种取值;
对于 i > ⌊ n ⌋ i >\lfloor\sqrt{n}\rfloor i>n ,有 ⌊ n i ⌋ ≤ ⌊ n ⌋ \left\lfloor\frac{n}{i}\right\rfloor \leq\lfloor\sqrt{n}\rfloor inn ,最多也只有 ⌊ n ⌋ \lfloor\sqrt{n}\rfloor n 种取值;
所以 ⌊ n i ⌋ \lfloor \frac n i \rfloor in 最多只有 2 n 2\sqrt n 2n 种取值。
(准确来说是 4 n + 1 − 1 \sqrt{4n+1} -1 4n+1 1 种取值)

那么我们就可以从前往后枚举,每到一个位置,找到其所在相同值区间的最右端位置,两位置相减+1便是区间长度,然后跳过这个区间。

那么如何得到相同值区间最右端位置呢?
设一段区间 [ l , r ] [l, r] [l,r] 中所有元素的值都为 k = ⌊ n l ⌋ k = \lfloor \frac n l \rfloor k=ln
现在要找到最大的 i i i 使得 k = ⌊ n i ⌋ k = \lfloor \frac n i \rfloor k=in 满足。
也就是,找到满足 i ≤ n k i \leq \frac n k ikn 的最大的 i i i,那么这个 i i i ⌊ n k ⌋ \lfloor \frac n k \rfloor kn,即 r = ⌊ n k ⌋ r = \lfloor \frac n k \rfloor r=kn
k = ⌊ n l ⌋ k = \left\lfloor \frac n l \right\rfloor k=ln 代入上式即得: r = ⌊ n ⌊ n l ⌋ ⌋ r = \left\lfloor {\frac {n}{\left\lfloor \frac n l \right\rfloor}} \right\rfloor r=lnn

所以我们只要在位置 l l l,就能得到和 ⌊ n l ⌋ \lfloor \frac n l \rfloor ln 值相同的区间最右端位置: r = ⌊ n ⌊ n l ⌋ ⌋ r = \left\lfloor {\frac {n}{\left\lfloor \frac n l \right\rfloor}} \right\rfloor r=lnn

那么对于求 ∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor i=1nin 就可以这样实现,复杂度 O ( n ) O(\sqrt n) O(n )

int ans = 0;
for(int l = 1, r; l <= n; l = r + 1) //l是枚举的i,r是相同值的最大i
{
	r = n/(n/l);
	ans += (r-l+1) * (n/l); //注意n/l的括号一定要加上,先整除再相乘
}
cout << ans;

下面来看几道例题:

例1:约数研究

Link
定义 f ( N ) f(N) f(N) N N N 的约数的个数。
∑ i = 1 n f ( i ) \sum_{i=1}^{n} f(i) i=1nf(i)

1 ≤ n ≤ 2 × 1 0 14 1≤ n ≤2×10^{14} 1n2×1014

思路
如果挨个求每个数的约数的话,复杂度是 O ( n n ) O(n\sqrt n) O(nn ),会超时。
转化思路,考虑 1~n 每个约数分别出现了多少次?
对于一个数 x 来说,肯定作为其所有倍数的约数,那 1~n 中 x 的倍数有 ⌊ n x ⌋ \lfloor \frac n x \rfloor xn 个,那这个约数就出现 ⌊ n x ⌋ \lfloor \frac n x \rfloor xn 次。遍历所有数累加其出现的次数。
所以题目就转化为求:
∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor i=1nin
就是模板题了。

Code

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define int long long

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];

signed main(){
	Ios;
	cin >> n;
	
	int ans = 0;
	for(int l = 1, r; l <= n; l = r + 1)
	{
		r = n/(n/l);
		ans += (r-l+1) * (n/l);
	}
	cout << ans;
	
	return 0;
}

例2:P2424 约数和

Link
定义 f ( N ) f(N) f(N) N N N 的约数之和。
给定 X , Y X,Y X,Y,求 f ( X ) + f ( X + 1 ) + ⋯ + f ( Y ) f(X)+f(X+1)+\dots+f(Y) f(X)+f(X+1)++f(Y)

1 ≤ n ≤ 2 × 1 0 14 1≤ n ≤2×10^{14} 1n2×1014

思路
我们可以仿照上一题的思路求 ∑ i = 1 n f ( i ) \sum_{i=1}^{n} f(i) i=1nf(i),然后用 ∑ i = 1 Y f ( i ) \sum_{i=1}^{Y} f(i) i=1Yf(i) 减去 ∑ i = 1 X − 1 f ( i ) \sum_{i=1}^{X-1} f(i) i=1X1f(i) 即可。

和上一题的思路一样,考虑每个约数的贡献。
对于每个约数 x,其出现了 ⌊ n x ⌋ \left\lfloor \frac n x \right\rfloor xn 次,那么这个约数之和就是 ⌊ n x ⌋ ∗ x \lfloor \frac n x \rfloor * x xnx
所以这题就转化为求:
∑ i = 1 n ⌊ n i ⌋ ∗ i \sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor * i i=1nini
对于一段区间 [l, r] 来说,其 ⌊ n i ⌋ \lfloor\frac{n}{i}\rfloor in 值相同,但是 i 值不同。
但由于 i 在同一区间,可以利用等差数列算出这一区间的 i 之和 sum,用 sum * ⌊ n i ⌋ \lfloor\frac{n}{i}\rfloor in 便是这段区间的贡献 ∑ i = l r ⌊ n i ⌋ ∗ i \sum_{i=l}^{r}\lfloor\frac{n}{i}\rfloor * i i=lrini

Code

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define int long long

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];

int sum_1(int n)
{
	return n * (n+1) / 2;
}

int ans(int n)
{
	int ans = 0;
	
	for(int l=1, r; l<=n; l=r+1)
	{
		r = n/(n/l);
		ans += (sum_1(r) - sum_1(l-1)) * (n/l);
	}
	return ans;
}

signed main(){
	Ios;
	cin >> n >> m;
	
	cout << ans(m) - ans(n-1);
	
	return 0;
}

例3:几番烟雾,只有花难护

Link
题目转化为,求:
∑ i = 1 n ⌈ n i ⌉ ∗ i 2 \sum_{i=1}^{n}\left\lceil \frac{n}{i} \right\rceil * i^2 i=1nini2
答案对 998244353 998244353 998244353 取模。

思路
上取整转化为下取整:
⌈ n i ⌉ = ⌊ n − 1 i ⌋ + 1 \left\lceil \frac{n}{i} \right\rceil = \left\lfloor \frac {n-1} i \right\rfloor +1 in=in1+1
注意这个公式只能在保证 n 不为 0 的情况下使用,n = 0 时出现错误为 1。
当 n 可能为 0 时可以用公式 ⌈ n i ⌉ = ⌊ n + i − 1 i ⌋ \left\lceil \frac{n}{i} \right\rceil = \left\lfloor \frac {n + i -1} i \right\rfloor in=in+i1

于是原式转化为:
∑ i = 1 n ⌊ n − 1 i ⌋ ∗ i 2 + ∑ i = 1 n i 2 \sum_{i=1}^{n}\left\lfloor\frac{n-1}{i} \right\rfloor* i^2 + \sum_{i=1}^{n} i^2 i=1nin1i2+i=1ni2
后半部分可以直接求出,前半部分和上一题类似,这题需要处理出区间的 i 2 i^2 i2 之和,乘以区间相同值 ⌊ n i ⌋ \left\lfloor\frac{n}{i}\right\rfloor in 即可。

需要知道:
1 2 + 2 2 + 3 2 + … + n 2 = n ( n + 1 ) ( 2 n + 1 ) 6 1^{2}+2^{2}+3^{2}+\ldots+\mathrm{n}^{2}=\frac{\mathrm{n}(\mathrm{n}+1)(2 \mathrm{n}+1)}{6} 12+22+32++n2=6n(n+1)(2n+1)

  • 除法要用逆元。

Code

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define int long long

const int N = 200010, mod = 998244353;
int T, n, m;
int a[N];

int qmi(int x, int y)
{
	int ans = 1;
	while(y)
	{
		if(y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}

int sum_2(int n)
{
	return n * (n + 1) % mod * (2*n + 1) % mod * qmi(6, mod-2) % mod;
}

signed main(){
	Ios;
	
	cin >> T;
	while(T--)
	{
		cin >> n;
		
		int ans = sum_2(n);
		
		int x = n-1;
		for(int l=1, r; l <= x; l = r+1)
		{
			r = x/(x/l);
			int t = (sum_2(r) - sum_2(l-1) + mod) % mod;
			ans = (ans + t * (x/l) % mod) % mod;
		}
		cout << ans << endl;
	}
	
	return 0;
}

此外还有
1 3 + 2 3 + … + n 3 = [ n ( n + 1 ) 2 ] 2 = ( 1 + 2 + … + n ) 2 1^{3}+2^{3}+\ldots+\mathrm{n}^{3}=\left[\frac{\mathrm{n}(\mathrm{n}+1)}{2}\right]^{2}=(1+2+\ldots+\mathrm{n})^{2} 13+23++n3=[2n(n+1)]2=(1+2++n)2


例4:P2261 [CQOI2007] 余数求和

Link
给出正整数 n n n k k k ,请计算 G ( n , k ) = ∑ i = 1 n k   m o d   i G(n, k)=\sum_{i=1}^{n} k \bmod i G(n,k)=i=1nkmodi

思路
k   m o d   i k\bmod i kmodi 不好处理,将其转化,等价于 k − i ∗ ⌊ k i ⌋ k - i* \left\lfloor \frac {k} {i} \right\rfloor kiik
原式转化为:
∑ i = 1 n k − i ∗ ⌊ k i ⌋ \sum_{i=1}^{n} k - i*\left\lfloor \frac k i \right\rfloor i=1nkiik
即:
∑ i = 1 n k − ∑ i = 1 n i ∗ ⌊ k i ⌋ \sum_{i=1}^{n} k - \sum_{i=1}^{n}i*\left\lfloor \frac k i \right\rfloor i=1nki=1niik
前半部分可以直接算出为 n*k,后半部分和例2一样,利用前缀和相减 * 区间值。

Code

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define int long long

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];
int k;

int sum(int l, int r)
{
	return (l+r)*(r-l+1)/2;
}

signed main(){
	cin >> n >> k;
	
	int ans = n * k;
	for(int l = 1, r; l <= min(n, k); l = r + 1) //注意这里只需要循环到min(n,k)。否则当l>k时,k/l=0, k/0无意义
	{
		r = min(n, k/(k/l)); //这里的右端点要和n取min
		ans -= sum(l, r) * (k/l);
	}
	cout << ans;
	
	return 0;
}

当枚举的除数 i 的范围和原数 x 不相同的话,要注意两个地方:

  • 枚举的除数 i 最大应该到 min(n, x)。因为当 i > x i > x i>x 时,x/i = 0,x/(x/i) 便会无意义。
  • r 的范围最大不超过 n,要和 n 取 min。当 n 和 x 相同时,n/(n/l) 一定不会超过 n,没问题。但是当 n 和 x 不同时,x/(x/l) 却可能大于 n,但是除数只需要枚举到 n,就加多了。

例5:求和公式

Link
给定 n , m n, m n,m 求:
∑ i = 1 n ∑ j = 1 m i 2 j ( n % i ) ( m % j ) \sum_{i=1}^{n} \sum_{j=1}^{m} i^{2} j(n \% i)(m \% j) i=1nj=1mi2j(n%i)(m%j)

10 ≤ n , m ≤ 1 0 9 10 \leq n,m \leq 10^9 10n,m109,答案取模 1 e 9 + 7 1e9+7 1e9+7

思路
首先观察出 i 和 j 没有联系,将其分开:
∑ i = 1 n i 2 ( n % i ) ∗ ∑ j = 1 m j ( m % j ) \sum_{i=1}^{n} i^{2} (n \% i)*\sum_{j=1}^{m}j(m \% j) i=1ni2(n%i)j=1mj(m%j)
将取模操作转化:
∑ i = 1 n i 2 ( n − i ∗ ⌊ n i ⌋ ) ∗ ∑ j = 1 m j ( m − j ∗ ⌊ m j ⌋ ) \sum_{i=1}^{n} i^{2} \left(n - i* \left\lfloor \frac n i \right\rfloor\right)*\sum_{j=1}^{m}j \left(m - j*\left\lfloor \frac m j\right\rfloor\right) i=1ni2(niin)j=1mj(mjjm)
即:
[ n ∗ ∑ i = 1 n i 2 − ∑ i = 1 n i 3 ∗ ⌊ n i ⌋ ] ∗ [ m ∗ ∑ j = 1 m j − ∑ j = 1 m j 2 ∗ ⌊ m j ⌋ ] \left[n*\sum_{i=1}^{n} i^{2} - \sum_{i=1}^{n} i^3* \left\lfloor \frac n i\right\rfloor\right] * \left[ m*\sum_{j=1}^{m} j - \sum_{j=1}^{m} j^2*\left\lfloor \frac m j\right\rfloor\right] [ni=1ni2i=1ni3in][mj=1mjj=1mj2jm]
而对于左右两个部分的前半部分都可以直接求出,后半部分和上例一样,利用前缀和相减 * 区间相同值。

Code

//https://ac.nowcoder.com/acm/contest/2891/C
#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define int long long

/*
	尽量保证运算过程中的每一个小块在参与下一步运算时都是正数。
	可以把每个小块单独拉出来写。 
*/

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];

int qmi(int x, int y)
{
	int ans = 1;
	while(y)
	{
		if(y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}

int sum_1(int n)
{
	return n * (n+1) % mod * qmi(2, mod - 2) % mod;
}

int sum_2(int n)
{
	return n * (n+1) % mod * (2*n + 1) % mod * qmi(6, mod - 2) % mod;
}

int sum_3(int n)
{
	int x = n * (n+1) % mod * qmi(2, mod - 2) % mod;
	return x * x % mod;
}

signed main(){
	Ios;
	cin >> n >> m;
	
	int ans1 = n * sum_2(n) % mod;
	for(int l = 1, r; l <= n; l = r + 1)
	{
		r = min(n, n/(n/l));
		int t = (sum_3(r) - sum_3(l-1) + mod) % mod;
		ans1 = (ans1 - t * (n/l) % mod + mod) % mod; //两数相乘之后一定先取模再进行其他操作 
	}
	
	int ans2 = m * sum_1(m) % mod;
	for(int l = 1, r; l <= m; l = r + 1)
	{
		r = min(m, m/(m/l));
		int t = (sum_2(r) - sum_2(l-1) + mod) % mod;
		ans2 = (ans2 - t * (m/l) % mod + mod) % mod;
	}
	
	cout << ans1 * ans2 % mod;
	
	return 0;
}

多维整除分块(N 维数论分块)

求形如下式的和式的值: ∑ i = 1 n ⌊ a 1 i ⌋ ⌊ a 2 i ⌋ ⋯ ⌊ a m i ⌋ \sum_{i=1}^{n}\left\lfloor\frac{a_{1}}{i}\right\rfloor\left\lfloor\frac{a_{2}}{i}\right\rfloor \cdots\left\lfloor\frac{a_{m}}{i}\right\rfloor i=1nia1ia2iam

每段区间的右端点 r = min ⁡ i = 1 m { [ a i ⌊ a i l ⌋ ⌋ } r=\min _{i=1}^{m}\left\{\left[\frac{a_{i}}{\left\lfloor\frac{a_{i}}{l}\right\rfloor}\right\rfloor\right\} r=mini=1m{[laiai} 即可,即取每一区间的右端点中最小的那个作为整体的右端点。

较常用的是 2 维数论分块:求 ∑ i = 1 n ⌊ n i ⌋ ⌊ m i ⌋ \sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor\left\lfloor\frac{m}{i}\right\rfloor i=1ninim 区间右端点 r = min ⁡ ( ⌊ n ⌊ n l ⌋ ⌋ , ⌊ m ⌊ m l ⌋ ⌋ ) r=\min\left(\left\lfloor\frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor,\left\lfloor\frac{m}{\left\lfloor\frac{m}{l}\right\rfloor}\right\rfloor\right) r=min(lnn,lmm),即 r = min(n, n/(n/l), m/(m/l))

时间复杂度仍为 O ( n ) O(\sqrt n) O(n )


例题:P2260 [清华集训2012] 模积和

Link
题意
求:
∑ i = 1 n ∑ j = 1 m ( n   m o d   i ) × ( m   m o d   j ) , i ≠ j \sum_{i = 1}^{n} \sum_{j = 1}^{m}(n \bmod i) \times(m \bmod j), i \neq j i=1nj=1m(nmodi)×(mmodj),i=j

  m o d     19940417 \bmod\ 19940417 mod 19940417 的值。

思路
乍一看和上一题的做法一样,将 i 和 j 分开分别处理就行了,但是要注意到一个条件: i ≠ j i \neq j i=j
可以用一个容斥,先不考虑相等的情况,分开 i 和 j 分别算出答案相乘之后再减去 i 和 j 相同情况的答案:
∑ i = 1 n ( n   m o d   i ) ∗ ∑ j = 1 m ( m   m o d   j ) − ∑ i = 1 m i n ( n , m ) ( n   m o d   i ) ( m   m o d   i ) \sum_{i=1}^{n} (n \bmod i)*\sum_{j=1}^{m}\left(m \bmod j\right) - \sum_{i=1}^{min(n, m)}\left(n \bmod i\right)\left(m \bmod i\right) i=1n(nmodi)j=1m(mmodj)i=1min(n,m)(nmodi)(mmodi)

前两项直接求解,最后一项化简:
∑ i = 1 n ( n   m o d   i ) ( m   m o d   i ) = ∑ i = 1 n ( n − ⌊ n i ⌋ i ) ( m − ⌊ m i ⌋ i ) = ∑ i = 1 n ( n m − ⌊ n i ⌋ i ⋅ m − ⌊ m i ⌋ i ⋅ n + ⌊ n i ⌋ ⌊ m i ⌋ i 2 ) = n 2 m − m ∑ i = 1 n ⌊ n i ⌋ i − n ∑ i = 1 n ⌊ m i ⌋ i + ∑ i = 1 n ⌊ n i ⌋ ⌊ m i ⌋ i 2 \sum_{i=1}^{n}(n \bmod i)(m \bmod i) \\=\sum_{i=1}^{n}\left(n-\left\lfloor\frac{n}{i}\right\rfloor i\right)\left(m-\left\lfloor\frac{m}{i}\right\rfloor i\right) \\ =\sum_{i=1}^{n}\left(n m-\left\lfloor\frac{n}{i}\right\rfloor i \cdot m-\left\lfloor\frac{m}{i}\right\rfloor i \cdot n+\left\lfloor\frac{n}{i}\right\rfloor\left\lfloor\frac{m}{i}\right\rfloor i^{2}\right) \\ =n^{2} m-m \sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor i-n \sum_{i=1}^{n}\left\lfloor\frac{m}{i}\right\rfloor i+\sum_{i=1}^{n}\left\lfloor\frac{n}{i}\right\rfloor\left\lfloor\frac{m}{i}\right\rfloor i^{2} i=1n(nmodi)(mmodi)=i=1n(nini)(mimi)=i=1n(nminimimin+inimi2)=n2mmi=1ninini=1nimi+i=1ninimi2

第 2,3 项都是模板,第 4 项就是一个 2 维数论分块。

Code

#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define int long long

const int N = 200010, mod = 19940417;
int T, n, m;
int a[N];
int inv2 = 9970209, inv6 = 3323403;

int x, y;
void exgcd(int a, int b)
{
	if (!b)
	{
		x = 1, y = 0;
		return;
	}
	exgcd(b, a % b);
	int tmp = x;
	x = y;
	y = tmp - a / b * y;
}

int inv(int a)
{
	exgcd(a, mod);
	x = (x % mod + mod) % mod;
	return x;
}

int sum_1(int n){
	return n * (n+1) % mod * inv2 % mod;
}

int sum_2(int n){
	return n * (n+1) % mod * (2*n+1) % mod * inv6 % mod;
}

int ans_1(int n, int x)
{
	int ans = 0;
	for(int l=1, r; l <= min(n, x); l = r+1)
	{
		r = min(n, x/(x/l));
		int t = (sum_1(r) - sum_1(l-1) + mod) % mod;
		ans = (ans + t * (x/l) % mod + mod) % mod;
	}
	return ans;
}

int ans_2(int n, int x, int y)
{
	int ans = 0;
	for(int l = 1, r; l <= n; l = r+1)
	{
		r = min(n, min(x/(x/l), y/(y/l)));
		int t = (sum_2(r) - sum_2(l-1) + mod) % mod;
		ans = (ans + t * (x/l) % mod * (y/l) % mod) % mod;
	}
	return ans;
}

signed main(){
	Ios;
	
	cin >> n >> m;
	
	int res1 = (n * n % mod - ans_1(n, n) + mod) % mod;
	int res2 = (m * m % mod - ans_1(m, m) + mod) % mod;
	int mina = min(n, m);
	int res3 = (n * m % mod * mina % mod - n * ans_1(mina, m) % mod - m * ans_1(mina, n) % mod
		+ ans_2(mina, n, m) + mod) % mod;
		
	cout << (res1 * res2 % mod - res3 + mod) % mod;
	
	return 0;
}

注意在该题中,模数 19940417 不是素数,则不能用快速幂求逆元,需要用扩展欧几里得。
逆元只求了 2 和 6 两个数,为了降低复杂度,可以预处理出来。


总结:

总之,整除分块就是一个可以以 O ( n ) O(\sqrt n) O(n ) 的复杂度求解形如 ∑ i = 1 n ⌊ a 1 i ⌋ ⌊ a 2 i ⌋ ⋯ ⌊ a m i ⌋ \sum_{i=1}^{n}\left\lfloor\frac{a_{1}}{i}\right\rfloor\left\lfloor\frac{a_{2}}{i}\right\rfloor \cdots\left\lfloor\frac{a_{m}}{i}\right\rfloor i=1nia1ia2iam 的问题的算法。

哪里有问题的话可以留言评论~


参考文章:
ACM竞赛中常见的整数公式与整数分块
OI Wiki - 数论分块
整数分块 —— 完美的根号n算法
【数论】整除分块(数论分块)
C -求和公式(整除分块)
【数学】数论分块(整除分块)
13+23+33+…+n3通项公式

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值