数论分块
数论分块可以快速计算一些形如
𝑛∑𝑖=1𝑓(𝑖)𝑔(⌊𝑛𝑖⌋)
的和式.如果可以在 𝑂(1) 时间内计算出 ∑𝑟𝑖=𝑙𝑓(𝑖)
 时间内计算出 ∑𝑟𝑖=𝑙𝑓(𝑖) 或已经预处理出 𝑓
 或已经预处理出 𝑓 的前缀和时,数论分块就可以在 𝑂(√𝑛)
 的前缀和时,数论分块就可以在 𝑂(√𝑛) 时间内计算出上述和式的值.
 时间内计算出上述和式的值.
数论分块常与 莫比乌斯反演 等技巧结合使用.
思路
首先,本文通过一个简单的例子来说明数论分块的思路.假设要计算如图所示的双曲线下的整点个数:

这相当于在计算和式:
11∑𝑖=1⌊11𝑖⌋.
这是前文所示和式在 𝑓(𝑘) =1, 𝑔(𝑘) =𝑘 时的特殊情况.
 时的特殊情况.
最简单的做法当然是逐列计算然后求和,但是这样需要计算第 𝑖 =1,2,⋯,11 列中每列整点的个数.观察图示可以发现,这些整点列的可以分成 5
 列中每列整点的个数.观察图示可以发现,这些整点列的可以分成 5 块,每块内点列的高度是一致的,形成一个矩形点阵.所以,只要能够知道这些块的宽度,就能够通过计算这些矩形块的大小快速完成统计.
 块,每块内点列的高度是一致的,形成一个矩形点阵.所以,只要能够知道这些块的宽度,就能够通过计算这些矩形块的大小快速完成统计.
这就是整除分块的基本思路.
性质
本节讨论关于双曲线 𝑦 =𝑛𝑥 下整点分块的若干结论.具体地,需要将 1 ∼𝑛
 下整点分块的若干结论.具体地,需要将 1 ∼𝑛 之间的整数按照 ⌊𝑛𝑖⌋
 之间的整数按照 ⌊𝑛𝑖⌋ 的取值分为若干块.设
 的取值分为若干块.设
𝐷𝑛={⌊𝑛𝑖⌋:1≤𝑖≤𝑛, 𝑖∈𝐍+}.
这就是 ⌊𝑛𝑖⌋ 所有可能的取值集合.
 所有可能的取值集合.
首先,这样的不同取值只有 𝑂(√𝑛) 个.所以,数论分块得到的块的数目只有 𝑂(√𝑛)
 个.所以,数论分块得到的块的数目只有 𝑂(√𝑛) 个.
 个.
性质 1
 |𝐷𝑛| ≤2√𝑛 .
.
证明
 分两种情况讨论:
 - 当 𝑖 ≤√𝑛 时,𝑖 时,𝑖 的取值至多 √𝑛 的取值至多 √𝑛 个,所以 ⌊𝑛𝑖⌋ 个,所以 ⌊𝑛𝑖⌋ 的取值也至多只有 √𝑛 的取值也至多只有 √𝑛 个. 个.
- 当 𝑖 >√𝑛 时,⌊𝑛𝑖⌋ ≤𝑛𝑖 <√𝑛 时,⌊𝑛𝑖⌋ ≤𝑛𝑖 <√𝑛 也至多只有 √𝑛 也至多只有 √𝑛 个取值. 个取值.
因此,所有可能取值的总数 |𝐷𝑛| ≤2√𝑛 .
.
然后,单个块的左右端点都很容易确定.
性质 2
 对于 𝑑 ∈𝐷𝑛 ,所有满足 ⌊𝑛𝑖⌋ =𝑑
,所有满足 ⌊𝑛𝑖⌋ =𝑑 的整数 𝑖
 的整数 𝑖 的取值范围为
 的取值范围为
 ⌊𝑛𝑑+1⌋+1≤𝑖≤⌊𝑛𝑑⌋.
证明
 因为 ⌊𝑛𝑖⌋ =𝑑 相当于不等式
 相当于不等式
 𝑑≤𝑛𝑖<𝑑+1. 
 这进一步等价于
 𝑛𝑑+1<𝑖≤𝑛𝑑. 
 利用 𝑖 ∈𝐍+ 这一点,可以对该不等式取整,它就等价于
 这一点,可以对该不等式取整,它就等价于
 ⌊𝑛𝑑+1⌋+1≤𝑖≤⌊𝑛𝑑⌋.
这一性质还体现了图像的对称性:每个块的右端点(前文图中的绿点)的集合恰为 𝐷𝑛 .这很容易理解,因为整个图像关于直线 𝑦 =𝑥
.这很容易理解,因为整个图像关于直线 𝑦 =𝑥 是对称的.
 是对称的.
除了这两条性质外,集合 𝐷𝑛 还具有良好的递归性质.这基于如下引理:
 还具有良好的递归性质.这基于如下引理:
引理
 对于 𝑎,𝑏,𝑐 ∈𝐍+ ,有
,有
 ⌊⌊𝑎/𝑏⌋𝑐⌋=⌊𝑎𝑏𝑐⌋.
证明
 令 𝑎 对于 𝑏
 对于 𝑏 做带余除法有 𝑎 =𝑞𝑏 +𝑟
 做带余除法有 𝑎 =𝑞𝑏 +𝑟 ,其中 𝑞,𝑟 ∈𝐍
,其中 𝑞,𝑟 ∈𝐍 且 𝑟 <𝑏
 且 𝑟 <𝑏 .需要证明的是
.需要证明的是
 ⌊𝑞𝑐⌋=⌊𝑞𝑐+𝑟𝑏𝑐⌋. 
 这等价于
 ⌊𝑞𝑐⌋≤𝑞𝑐+𝑟𝑏𝑐<⌊𝑞𝑐⌋+1. 
 左侧不等式是显然的.关键是要证明右侧不等式.为此,令 𝑞 对 𝑐
 对 𝑐 做带余除法,就有
 做带余除法,就有
 𝑞=⌊𝑞𝑐⌋𝑐+𝑟′, 
 其中,0 ≤𝑟′ ≤𝑐 −1 .所以,有
.所以,有
 𝑞≤⌊𝑞𝑐⌋𝑐+𝑐−1⟺𝑞+1𝑐≤⌊𝑞𝑐⌋+1. 
 进而,利用 𝑟 <𝑏 ,就有
,就有
 𝑞𝑐+𝑟𝑏𝑐<𝑞+1𝑐≤⌊𝑞𝑐⌋+1. 
 这就证明右侧不等式,进而完成本命题的证明.
这一引理经常出现在数论分块的各种应用中.利用该引理可以得到如下性质:
性质 3
 对于 𝑚 ∈𝐷(𝑛) ,有 𝐷(𝑚) ⊆𝐷(𝑛)
,有 𝐷(𝑚) ⊆𝐷(𝑛) .
.
证明
 设 𝑚 =⌊𝑛𝑘⌋ ,那么,因为对于所有 𝑖 ∈𝐍+
,那么,因为对于所有 𝑖 ∈𝐍+ ,都有
,都有
 ⌊𝑚𝑖⌋=⌊⌊𝑛/𝑘⌋𝑖⌋=⌊𝑛𝑘𝑖⌋∈𝐷(𝑛), 
 所以,𝐷(𝑚) ⊆𝐷(𝑛) .
.
前文已经提到,𝐷(𝑛) 既是每块中 ⌊𝑛𝑖⌋
 既是每块中 ⌊𝑛𝑖⌋ 的取值集合,也是每块的右端点集合.这意味着,如果要递归地应用数论分块(即函数在 𝑛
 的取值集合,也是每块的右端点集合.这意味着,如果要递归地应用数论分块(即函数在 𝑛 处的值依赖于它在 𝑚 ∈𝐷(𝑛) ∖{𝑛}
 处的值依赖于它在 𝑚 ∈𝐷(𝑛) ∖{𝑛} 处的值),那么在整个计算过程中所涉及的取值集合和右端点集合,其实都是 𝐷(𝑛)
 处的值),那么在整个计算过程中所涉及的取值集合和右端点集合,其实都是 𝐷(𝑛) .一个典型的例子是 杜教筛.
.一个典型的例子是 杜教筛.
过程
利用上一节叙述的结论,就得到数论分块的具体过程.
为计算和式
𝑛∑𝑖=1𝑓(𝑖)𝑔(⌊𝑛𝑖⌋)
的取值,可以依据 ⌊𝑛𝑖⌋ 的取值将标号 𝑖 =1,2,⋯,𝑛
 的取值将标号 𝑖 =1,2,⋯,𝑛 分块.因为 ⌊𝑛𝑖⌋
 分块.因为 ⌊𝑛𝑖⌋ 取值相同的标号是一段连续整数 [𝑙,𝑟]
 取值相同的标号是一段连续整数 [𝑙,𝑟]![[l,r]](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7) ,所以该块中和式的取值为
,所以该块中和式的取值为
(𝑟∑𝑖=𝑙𝑓(𝑖))⋅𝑔(⌊𝑛𝑙⌋).
为了快速计算该和式,通常需要能够快速计算左侧关于 𝑓 的和式.有些时候,该和式的表达式是已知的,可以在 𝑂(1)
 的和式.有些时候,该和式的表达式是已知的,可以在 𝑂(1) 时间内完成单次计算;有些时候,可以预处理出它的前缀和,仍然可以在 𝑂(1)
 时间内完成单次计算;有些时候,可以预处理出它的前缀和,仍然可以在 𝑂(1) 时间内完成单次查询.
 时间内完成单次查询.
在顺次计算每块左右端点时,当前块的左端点 𝑙 就等于前一块的右端点再加 1
 就等于前一块的右端点再加 1 ,而当前块的右端点就等于 ⌊𝑛⌊𝑛/𝑙⌋⌋
,而当前块的右端点就等于 ⌊𝑛⌊𝑛/𝑙⌋⌋ .由此,可以得到如下伪代码:
.由此,可以得到如下伪代码:
𝐀𝐥𝐠𝐨𝐫𝐢𝐭𝐡𝐦 Sum(𝑓,𝑔,𝑛):𝐈𝐧𝐩𝐮𝐭. 𝑛, 𝑠(𝑘)=∑𝑘𝑖=1𝑓(𝑘), 𝑔(𝑘).𝐎𝐮𝐭𝐩𝐮𝐭. 𝑆(𝑛)=∑𝑛𝑖=1𝑓(𝑖)𝑔(⌊𝑛/𝑖⌋).𝐌𝐞𝐭𝐡𝐨𝐝.1𝑙←12𝑟𝑒𝑠𝑢𝑙𝑡←03𝐰𝐡𝐢𝐥𝐞 𝑙≤𝑛 𝐝𝐨4𝑟←⌊𝑛⌊𝑛/𝑙⌋⌋5𝑟𝑒𝑠𝑢𝑙𝑡←𝑟𝑒𝑠𝑢𝑙𝑡+(𝑠(𝑟)−𝑠(𝑙−1))⋅𝑔(⌊𝑛𝑙⌋)6𝑙←𝑟+17𝐞𝐧𝐝 𝐰𝐡𝐢𝐥𝐞8𝐫𝐞𝐭𝐮𝐫𝐧 𝑟𝑒𝑠𝑢𝑙𝑡
假设单次计算 𝑠( ⋅) 的时间复杂度为 𝑂(1)
 的时间复杂度为 𝑂(1) ,则整个过程的时间复杂度为 𝑂(√𝑛)
,则整个过程的时间复杂度为 𝑂(√𝑛) .
.
扩展
前文讨论的是数论分块的最常见也最基本的形式.本节进一步讨论数论分块的扩展形式.
向上取整的数论分块
数论分块可以用于计算含有向上取整的和式:
𝑛∑𝑖=1𝑓(𝑖)𝑔(⌈𝑛𝑖⌉).
因为 ⌈𝑛𝑖⌉ =⌊𝑛−1𝑖⌋ +1 ,该和式可以转化为向下取整的情形:
,该和式可以转化为向下取整的情形:
𝑓(𝑛)𝑔(1)+𝑛−1∑𝑖=1𝑓(𝑖)𝑔(⌊𝑛−1𝑖⌋+1).
注意到求和的上限发生了变化,以及 𝑖 =𝑛 时单独的一项.
 时单独的一项.
多维数论分块
数论分块还可以用于处理包含不只有一个取整式的和式:
𝑛∑𝑖=1𝑓(𝑖)𝑔(⌊𝑛1𝑖⌋,⌊𝑛2𝑖⌋,⋯,⌊𝑛𝑚𝑖⌋).
为了应用数论分块的思想,需要保证每块中所有取整式 ⌊𝑛1𝑖⌋,⌊𝑛2𝑖⌋,⋯,⌊𝑛𝑚𝑖⌋ 的取值都不发生变化,也就是说,多维的块应当是所有一维的块的交集.为此,对于已知的左端点 𝑙
 的取值都不发生变化,也就是说,多维的块应当是所有一维的块的交集.为此,对于已知的左端点 𝑙 ,相应的右端点为
,相应的右端点为
min{⌊𝑛1⌊𝑛1/𝑙⌋⌋,⌊𝑛2⌊𝑛2/𝑙⌋⌋,⋯,⌊𝑛𝑚⌊𝑛𝑚/𝑙⌋⌋}.
也就是说,对于所有一维分块的右端点取最小值,作为多维分块的右端点.可以借助下图理解:

较为常见的是二维形式,此时可将前述伪代码中 𝑟 ←⌊𝑛⌊𝑛/𝑙⌋⌋ 替换成
 替换成
𝑟←min{⌊𝑛1⌊𝑛1/𝑙⌋⌋,⌊𝑛2⌊𝑛2/𝑙⌋⌋}.
任意指数数论分块
数论分块可以用于含有任意指数的取整式的和式计算:
⌊𝑛𝛼/𝛽⌋∑𝑖=1𝑓(𝑖)𝑔(⌊𝑛𝛼𝑖𝛽⌋).
其中,𝛼,𝛽 为正实数.本文讨论的基本形式中,𝛼 =𝛽 =1
 为正实数.本文讨论的基本形式中,𝛼 =𝛽 =1 .
.
性质
 对于正整数 𝑛 和正实数 𝛼,𝛽
 和正实数 𝛼,𝛽 ,设
,设
 𝐷𝑛,𝛼,𝛽={⌊𝑛𝛼𝑖𝛽⌋:𝑖=1,2,⋯,⌊𝑛𝛼/𝛽⌋}. 
 那么,有
 - |𝐷𝑛,𝛼,𝛽| ≤2𝑛𝛼/(1+𝛽) . .
- 对于 𝑑 ∈𝐷𝑛,𝛼,𝛽 ,使得 ⌊𝑛𝛼𝑖𝛽⌋ =𝑑 ,使得 ⌊𝑛𝛼𝑖𝛽⌋ =𝑑 成立的 𝑖 成立的 𝑖 的取值范围为 的取值范围为
 ⌊𝑛𝛼/𝛽(𝑑+1)1/𝛽⌋+1≤𝑖≤⌊𝑛𝛼/𝛽𝑑1/𝛽⌋. 
证明
 对于第一点,分两种情况:
 - 当 𝑖 ≤𝑛𝛼𝑖𝛽 时,有 𝑖 ≤𝑛𝛼/(1+𝛽) 时,有 𝑖 ≤𝑛𝛼/(1+𝛽) ,所以 ⌊𝑛𝛼𝑖𝛽⌋ ,所以 ⌊𝑛𝛼𝑖𝛽⌋ 至多有 𝑛𝛼/(1+𝛽) 至多有 𝑛𝛼/(1+𝛽) 种取值. 种取值.
- 当 𝑖 >𝑛𝛼𝑖𝛽 时,有 𝑖 >𝑛𝛼/(1+𝛽) 时,有 𝑖 >𝑛𝛼/(1+𝛽) ,进而有 𝑛𝛼𝑖𝛽 <𝑛𝛼/(1+𝛽) ,进而有 𝑛𝛼𝑖𝛽 <𝑛𝛼/(1+𝛽) ,所以 ⌊𝑛𝛼𝑖𝛽⌋ ,所以 ⌊𝑛𝛼𝑖𝛽⌋ 也至多只有 𝑛𝛼/(1+𝛽) 也至多只有 𝑛𝛼/(1+𝛽) 种取值. 种取值.
综合两种情形,就有 |𝐷𝑛,𝛼,𝛽| ≤2𝑛𝛼/(1+𝛽) .
.
 对于第二点,⌊𝑛𝛼𝑖𝛽⌋ =𝑑 就等价于
 就等价于
 𝑑≤𝑛𝛼𝑖𝛽<𝑑+1⟺𝑛𝛼/𝛽(𝑑+1)1/𝛽<𝑖≤𝑛𝛼/𝛽𝑑1/𝛽. 
 对该不等式取整,就得到第二个命题.
利用这些性质,就可以在 𝑂(𝑛𝛼/(1+𝛽)) 的时间复杂度下实现对任意指数的数论分块.
 的时间复杂度下实现对任意指数的数论分块.
例子
 例如,对于 𝛼 =𝛽 =1/2 时的如下和式
 时的如下和式
 𝑛∑𝑖=1𝑓(𝑖)𝑔(⌊√𝑛𝑖⌋), 
 可以通过数论分块在 𝑂(𝑛1/3) 时间内解决.已知块的左端点为 𝑙
 时间内解决.已知块的左端点为 𝑙 时,可以计算右端点为 𝑟 =⌊𝑛⌊√𝑛/𝑙⌋2⌋
 时,可以计算右端点为 𝑟 =⌊𝑛⌊√𝑛/𝑙⌋2⌋ .
.
例题
UVa11526 H(n)
 𝑇 组数据,每组一个整数 𝑛
 组数据,每组一个整数 𝑛 .对于每组数据,输出 ∑𝑛𝑖=1⌊𝑛𝑖⌋
.对于每组数据,输出 ∑𝑛𝑖=1⌊𝑛𝑖⌋ .
.
解答
 根据前文分析,可以对于每一块相同的 ⌊𝑛𝑖⌋ 一起计算.时间复杂度为 𝑂(𝑇√𝑛)
 一起计算.时间复杂度为 𝑂(𝑇√𝑛) .
.
实现
 |  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | #include <iostream>
long long H(int n) {
  long long res = 0;  // 储存结果
  int l = 1, r;       // 块左端点与右端点
  while (l <= n) {
    r = n / (n / l);  // 计算当前块的右端点
    // 累加这一块的贡献到结果中。乘上 1LL 防止溢出
    res += 1LL * (r - l + 1) * (n / l);
    l = r + 1;  // 左端点移到下一块
  }
  return res;
}
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  int t, n;
  std::cin >> t;
  while (t--) {
    std::cin >> n;
    std::cout << H(n) << '\n';
  }
  return 0;
}
 | 
Codeforces 1954E Chain Reaction
 有一排 𝑛 只怪兽,每只怪兽初始血量为 𝑎𝑖
 只怪兽,每只怪兽初始血量为 𝑎𝑖 .一次攻击会使一段连续的存活的怪兽血量减 𝑘
.一次攻击会使一段连续的存活的怪兽血量减 𝑘 ,血量不大于 0
,血量不大于 0 视作死亡.对于所有 𝑘
 视作死亡.对于所有 𝑘 求出击杀所有怪兽所需攻击次数.其中,𝑛,𝑎𝑖 ≤105
 求出击杀所有怪兽所需攻击次数.其中,𝑛,𝑎𝑖 ≤105 .
.
解答
 令 𝑎0 =0 .假设击杀所有前 (𝑖 −1)
.假设击杀所有前 (𝑖 −1) 只怪兽需要 𝑇(𝑘,𝑖 −1)
 只怪兽需要 𝑇(𝑘,𝑖 −1) 次攻击,第 𝑖
 次攻击,第 𝑖 只怪兽的血量为 𝑎𝑖
 只怪兽的血量为 𝑎𝑖 .由于击杀第 (𝑖 −1)
.由于击杀第 (𝑖 −1) 只怪兽时,需要攻击它 ⌈𝑎𝑖−1/𝑘⌉
 只怪兽时,需要攻击它 ⌈𝑎𝑖−1/𝑘⌉ 次,这些攻击都可以延伸到第 𝑖
 次,这些攻击都可以延伸到第 𝑖 只怪兽.因此,要击杀第 𝑖
 只怪兽.因此,要击杀第 𝑖 只怪兽,只需要再攻击 max{0,⌈𝑎𝑖/𝑘⌉ −⌈𝑎𝑖−1/𝑘⌉}
 只怪兽,只需要再攻击 max{0,⌈𝑎𝑖/𝑘⌉ −⌈𝑎𝑖−1/𝑘⌉} 次.由此,总的攻击次数为
 次.由此,总的攻击次数为
 𝑇(𝑘,𝑛)=𝑛∑𝑖=1max(0,⌈𝑎𝑖𝑘⌉−⌈𝑎𝑖−1𝑘⌉). 
 由于题目涉及的 𝑛,𝑘 都比较大,对每个 𝑘
 都比较大,对每个 𝑘 分别计算该和式并不可行.可以考虑对每个 𝑖 =1,2,⋯,𝑛
 分别计算该和式并不可行.可以考虑对每个 𝑖 =1,2,⋯,𝑛 ,都维护数列 {𝑇(𝑘,𝑖)}𝑘
,都维护数列 {𝑇(𝑘,𝑖)}𝑘 .初始时,设 𝑇(𝑘,0) ≡0
.初始时,设 𝑇(𝑘,0) ≡0 .假设数列 {𝑇(𝑘,𝑖 −1)}𝑘
.假设数列 {𝑇(𝑘,𝑖 −1)}𝑘 已知,考虑如何对它进行修改才能得到数列 {𝑇(𝑘,𝑖)}𝑘
 已知,考虑如何对它进行修改才能得到数列 {𝑇(𝑘,𝑖)}𝑘 .根据前文分析,只需要对数列的第 𝑘
.根据前文分析,只需要对数列的第 𝑘 项增加 max(0,⌈𝑎𝑖𝑘⌉−⌈𝑎𝑖−1𝑘⌉)
 项增加 max(0,⌈𝑎𝑖𝑘⌉−⌈𝑎𝑖−1𝑘⌉) 即可.利用二维数论分块,可以将这一修改操作拆分成 𝑂(√𝑎𝑖−1 +√𝑎𝑖)
 即可.利用二维数论分块,可以将这一修改操作拆分成 𝑂(√𝑎𝑖−1 +√𝑎𝑖) 段区间修改操作,且每段区间上增加的值是固定的.最后得到的数列 {𝑇(𝑘,𝑛)}𝑘
 段区间修改操作,且每段区间上增加的值是固定的.最后得到的数列 {𝑇(𝑘,𝑛)}𝑘 就是答案.
 就是答案.
 由于题目涉及一系列区间加操作,且查询只发生所有修改完成后.所以,可以通过维护差分序列进行区间加修改,最后通过求前缀和得到所求数列.总的时间复杂度为 𝑂(∑√𝑎𝑖) .本题也存在其他解法.
.本题也存在其他解法.
实现
 |  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | #include <algorithm>
#include <iostream>
constexpr int N = 100009;
int n, a[N], maxn;
long long ans[N];
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cin >> n;
  for (int i = 1; i <= n; ++i) {
    std::cin >> a[i];
    maxn = std::max(maxn, a[i]);
  }
  for (int i = 0; i < n; ++i)
    for (int l = 1, r;; l = r + 1) {
      r = std::min(l < a[i] ? (a[i] - 1) / ((a[i] - 1) / l) : N,
                   l < a[i + 1] ? (a[i + 1] - 1) / ((a[i + 1] - 1) / l)
                                : N);  // 二维数论分块
      if (r == N) break;
      int x = (a[i + 1] - 1) / l - std::max(a[i] - 1, 0) / l;
      if (x > 0) ans[l] += x, ans[r + 1] -= x;  // 累加贡献
    }
  ++ans[0];  // ⌈a/l⌉=(a-1)/l+1的式子当a=0时不成立,需要修正
  for (int i = 1; i <= maxn; ++i)
    std::cout << (ans[i] += ans[i - 1]) << " \n"[i == maxn];
  return 0;
}
 | 
习题
参考资料与注释
本页面最近更新:2025/9/23 18:21:11,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:Tiphereth-A, c-forrest, Xeonacid, yusancky, 2044-space-elevator, 383494, 99-woods, Backl1ght, caijianhong, CCXXXI, ghszt0, Great-designer, iamtwz, ksyx, Marcythm, qwqAutomaton, sshwy, StudyingFather, tder6, TOMWT-qwq
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用