嘘~ 正在从服务器偷取页面 . . .

OI数学总结-数论


OI数学总结-数论

注意,本文不同于 OI模板-数学

本文倾向于数学概念,但是包含部分代码,只是因为数论的内容与代码联系紧密,因此显得较为相似。


积性函数

数论中定义:定义域为正整数域的函数 \(f(n)\)

且满足 \(\forall a,b \in \mathbb{Z} _+,f(ab)=f(a)f(b) \land \gcd(a,b)=1\)


完全积性函数

数论中定义:定义域为正整数域的函数 \(f(n)\)

且满足 \(\forall a,b \in \mathbb{Z} _+,f(ab)=f(a)f(b)\)


最大公约数 gcd

最大公约数指能够整除多个不全为零的整数的最大正整数

常用性质: \(a\times b = \gcd(a,b) \times \mathrm{lcm}(a,b)\)

代码求解

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
} // 注意这份代码对于(+,-)的情况会求出负数

裴蜀定理

\(a,b\)不全为零的整数,则存在整数,使得 \(ax+by=\gcd(a,b)\)

证明详见 裴蜀定理及其证明


扩展欧几里德算法(Exgcd)

板子题: P5656 【模板】二元一次不定方程 (exgcd)

\(b \ne 0\) ,扩展欧几里得算法求出的可行解必有 \(|x| \le b ,|y| \le a\)

int exgcd(int a,int b,int &x,int &y)
{
    int d=a;
    if(!b)x=1,y=0;
    else d=exgcd(b,a%b,y,x),y-=a/b*x;
    return d;
}
void solve()
{
    int a,b,c,x,y;
    read(a);read(b);read(c);
    int d=exgcd(a,b,x,y);
    if(c%d!=0){puts("-1");return;} // 无解
    x*=c/d;y*=c/d;
    int p=b/d,q=a/d,k;
    if(x<0)k=ceil((1.0-x)/p),x+=p*k,y-=q*k; // 将x提高到最小正整数
    else k=(x-1)/p,x-=p*k,y+=q*k; // 将x降低到最小正整数
    if(y>0) // 存在x>0,y>0的解(正整数)
    {
        write((y-1)/q+1);   pc(' '); // 将y减到1的方案数即为解的个数
        write(x);           pc(' '); // 当前的x为最小正整数
        write((y-1)%q+1);   pc(' '); // 将y取到最小正整数
        write(x+(y-1)/q*p); pc(' '); // 将x提升到最大
        write(y);           pc(' '); // 特解即为y的最大值
    }else // 仅存在整数解
    {
        write(x);                       pc(' '); // 当前的x
        write(y+q*(int)ceil((1.0-y)/q));pc(' '); // 将y提高到正整数
    }
    pc('\n');
}

费马小定理

  1. \(p\) 为素数 , \(\gcd(a,p)=1\)\(a^{p-1}\equiv 1 \pmod{p}\)

  2. \(p\) 为素数 ,则对于任意整数 \(a\) ,有 \(a^p \equiv a \pmod{p}\)

常用于 \(O(\log n)\) 求解 \(n\) 模素数 \(p\) 意义下的逆元,详见逆元部分。


逆元

如果一个线性同余方程组 \(ax \equiv 1 \pmod{b}\) ,则 \(x\) 称为 \(a \bmod b\) 的逆元,记作 \(a^{-1}\)

模意义下的乘法逆元不唯一。

如果 \(b\) 不为素数,可能不存在逆元。

代码求解

P3811 【模板】乘法逆元

\(O(n)\) 预处理 ,\(O(1)\) 查询

求的是 \(1,2,\cdots ,n\) 的模 \(p\) 意义下的乘法逆元,\(p\) 一般为质数。

为什么说一般呢?因为「 \(p\) 为合数」会导致有些时候不存在逆元

如果正好存在逆元也是可以继续做的。

原理: \[ \begin{aligned} i^{-1} &\equiv \begin{cases} 1,&\text{if }i=1,\\\\ -\left\lfloor\dfrac{p}{i}\right\rfloor \left(p\bmod{i}\right)^{-1}, &\text{otherwises.} \end{cases} \pmod{p} \end{aligned} \]

注意空间复杂度为 \(O(n)\)

inv[1]=1;
for(int i=2; i<=n; i++)
    inv[i]=(p-p/i)*inv[p%i]%p;

费马小定理 \(O(\log p)\) 查询 \(x\) 的逆元

原理:\(x \equiv a^{p-2}\pmod{p}\) (根据费马小定理)

\(p\) 需要是质数

cout << qpow(a,p-2) << '\n'; // 快速幂

\(\text{Exgcd}~O(\log p)\) 查询 \(x^{-1}\)

求的是 \(a\) 在模 \(p\) 意义下的逆元,要求模数 \(p\)\(a\) 互质。

int exgcd(int a,int b,int &x,int &y)
{
    int d=a;
    if(!b)x=1,y=0;
    else d=exgcd(b,a%b,y,x),y-=a/b*x;
    return d;
}
int solve(int a,int p)
{
	int x,y;
    exgcd(a,p,x,y);
    x=(x%p+p)%p;
    return x;
}

\(\mathcal{O}(n)\) 预处理阶乘的逆元

因为 \(n!=(n-1)! \times n\) ,所以 \(((n-1)!)^{-1}=(n!)^{-1} \times n\) 。模数 \(p\)质数

for(int i=1; i<=n; i++) fac[i] = fac[i-1] * i % p;
invf[n] = qpow(fac[n], p-2); // 费马小定理
for(int i=n-1; i>=1; i--) invf[i] = invf[i+1] * (i+1) % p;

请注意,如果 \(p \le n\) ,这种方法就不可行了,因为 \(n! \bmod p =0\) ,会出现不存在逆元的情况

这种时候一般采用上文线性求逆元的方法,只要求 \(1\sim p-1\) 的就行了,即

// luogu P2675
for(int i=1; i<=n; i++) fac[i] = fac[i-1] * i % p;
for(int i=2; i<p; i++) inv[i] = (p-p/i) * inv[p%i] % p; // 注意是1 ~ p-1

欧拉函数

欧拉函数 \(\varphi(n)\) 表示小于等于 \(n\)\(n\) 互质的数的个数。

\(n=\prod_{i=1}^{s}p_i^{k_i}\) \[ \varphi(n) = n \prod\limits_{i=1}^s\left(\dfrac{p_i-1}{p_i}\right) = \prod(p_i-1)\times p_i^{k_i-1} \]

常用性质:\(\varphi(1) = 1,~\varphi(p) = p-1,~p\in\mathbb{P}\) ,以及 \(n > 2\) 时,\(\varphi(n)\) 为偶数

代码求解

\(O(\sqrt{n})\)\(\varphi(n)\)

板子题:poj2407

int Euler_phi(int n)
{
    int ans=n;
    for(int i=2; i<=n/i; i++)
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0)n/=i;
        }
    if(n>1)ans=ans/n*(n-1);
    return ans;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n;
    while(cin>>n&&n!=0)
        cout << Euler_phi(n) << endl;

    return 0;
}

线性筛 \(O(n)\) 求解

poj2478 (这个题要改成 \(\varphi\) 的前缀和)

int phi[N],prime[N],pcnt;
bool ck[N];
void Euler()
{
    ck[1]=1;
    phi[1]=1;
    for(int i=2; i<=N-5; i++)
    {
        if(!ck[i])
        {
            prime[++pcnt]=i;
            phi[i]=i-1;
        }
        for(int j=1; j<=pcnt&&i*prime[j]<=N-5; j++)
        {
            int pos=i*prime[j];
            ck[pos]=1;
            if(i%prime[j])
            {
                phi[pos]=phi[i]*phi[prime[j]];
            }
            else
            {
                phi[pos]=phi[i]*prime[j];
                break;
            }
        }
    }
}

欧拉定理

\(\gcd(a,m) = 1\) ,则 \(a^{\varphi(m)} \equiv 1\pmod{m}\)

\(m\) 为素数时,根据欧拉函数的性质有 \(a^{m-1}\equiv 1 \pmod{m}\) ,即费马小定理


扩展欧拉定理

\[ \begin{aligned} a^b \equiv \begin{cases} a^b,&b< \varphi(m)\\\\ a^{b \ \bmod \ \varphi(m)+\varphi(m)},&b\ge \varphi(m) \end{cases} \pmod{m} \end{aligned} \]

应用

例题:

\[ a^b\bmod m \] \(1\le a,m\le 10^{12},1\le b\le 10^{20000000}\)(这个是加强版的,朴素版只要int就行)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define gc() getchar()
int a,m,b,flag;
int Euler_phi(int n)
{
    int ans=n;
    for(int i=2; i<=n/i; i++)
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0)n/=i;
        }
    if(n>1)ans=ans/n*(n-1);
    return ans;
}
int qpow(int a,int b,int p)
{
    int ans=1,base=a%p;
    while(b)
    {
        if(b&1)ans=(__int128)ans*base%p;
        base=(__int128)base*base%p;
        b>>=1;
    }
    return ans;
}
signed main()
{
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    scanf("%lld%lld",&a,&m);
    a%=m;
    int phi=Euler_phi(m);
    char ch=gc();
    while(!isdigit(ch))ch=gc();
    while(isdigit(ch))
    {
        b=(b<<1)+(b<<3)+(ch^48);
        if(b>=phi)flag=1,b%=phi;ch=gc();
    }
    if(b>=phi)flag=1,b%=phi;
    if(flag)b+=phi;
    printf("%lld\n",qpow(a,b,m));
    return 0;
}

Lucas定理

对于质数 \(p\) ,有 \[ \dbinom{n}{m} \bmod p = \dbinom{\left\lfloor{n/p}\right\rfloor}{\left\lfloor{m/p}\right\rfloor} \times \dbinom{n \bmod p}{m \bmod p} \bmod p \] \(\binom{\left\lfloor{n/p}\right\rfloor}{\left\lfloor{m/p}\right\rfloor}\) 采用递归处理,后面的直接 \(O(p)\) 预处理组合数

板子题:P3807 【模板】卢卡斯定理/Lucas 定理

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <random>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(2e5+15)
int Q,n,m,p;
int fac[N];
int qpow(int a,int b,int p)
{
	int ans=1,base=a;
	while(b)
	{
		if(b&1)ans=ans*base%p;
		base=base*base%p;
		b>>=1;
	}
	return ans;
}
// n 选 m
int C(int n,int m,int p)
{
	if(n<m)return 0;
	return fac[n]*qpow(fac[m],p-2,p)%p*qpow(fac[n-m],p-2,p)%p;
}
int lucas(int n,int m,int p)
{
	if(!m)return 1;
	return lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}
signed main()
{
	cin >> Q;
	while(Q--)
	{
		cin >> n >> m >> p;
		fac[1]=fac[0]=1;
		for(int i=2; i<=n+m; i++)
			fac[i]=fac[i-1]*i%p;
		cout << lucas(n+m,m,p) << '\n'; // C(n+m,n)
	}
	return 0;
}

中国剩余定理

参考 中国剩余定理 & 扩展

中国剩余定理(CRT)可求解如下形式的一元线性同余方程组 \[ \begin{cases} x \equiv a_1\ \pmod{p_1} \\[6pt] x\equiv a_2\ \pmod{p_2} \\[6pt] \quad\vdots \\[6pt] x \equiv a_n\ \pmod{p_k}\end{cases} \] 其中 \(p_1,p_2,\cdots,p_k\) 两两互质

板子题:P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪

算法原理很简单

  1. 计算 \(P = \prod p_i\)
  2. \(m_i = \frac{P}{p_i}\)\(m_i^{-1}\) 为模 \(p_i\) 意义下的乘法逆元,求 \(c_i = m_im_i^{-1}\)
  3. 方程组的唯一解 \(x = \sum_{i=1}^{k}a_ic_i\pmod{P}\)

证明就不讲了,中国剩余定理主要还是流程比较难记(确信)

时间复杂度 \(\mathcal{O}(n \log V)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(15))

int a[N],p[N];
void exgcd(int a, int b, int &x, int &y)
{
	if(!b) { x = 1, y = 0; }
	else exgcd(b, a % b, y, x), y -= a / b * x;
}
int solve(int n, int P)
{
	int res = 0;
	for(int i = 1; i <= n; i++)
	{
		int m = P / p[i], x, y;
		exgcd(m, p[i], x, y); // m * x % p[i] = 1;
		res = (res + a[i] * m % P * x % P) % P;
	}
	return (res % P + P) % P;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	// freopen("check.in","r",stdin);
	// freopen("check.out","w",stdout);
	int n, P = 1; cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> p[i] >> a[i]; P = P * p[i];
	}
	cout << solve(n, P) << '\n';
	return 0;
}

扩展中国剩余定理

ExCRT 用于解决 \(p_i\) 不一定互质的情况

设两个方程为 \(x \equiv a_1 \pmod{p_1},~x \equiv a_2 \pmod{p_2}\)

可得 \[ x = p_1\cdot u +a_1 = p_2\cdot v + a_2 \] 因此 \[ p_1 \cdot u - p_2 \cdot v = a_2 - a_1 \]\(c = (a_2 - a_1)\) 。由裴蜀定理, 当且仅当 \(\gcd(p_1,p_2)\mid c\) 时有解。

于是我们可以通过 exgcd 求出一对 \(u_1,v_1\) ,满足 \(p_1\cdot u_1 + p_2 \cdot v_1=g\)\(-p_2\) 与此实际上等价)

\(g = \gcd(p_1,p_2)\) ,显然 \(p_1u_1 \cdot \frac{c}{g} + p_2v_1 \cdot \frac{c}{g} = c\) ,则 \[ \begin{cases} u = u_1 \cdot \frac{c}{g} + \frac{p_2}{g}\cdot k \\[8pt]v = v_1 \cdot \frac{c}{g} - \frac{p_1}{g}\cdot k \end{cases} \] 为一组通解。于是我们求最小的解 \(u_0 \equiv u_1 \cdot \frac{c}{g} \pmod{\frac{p_2}{g}}\) ,钦定 \(u_0 > 0\) (都是为了方便和防止溢出)。

那么原方程就可以写作 \[ x \equiv p_1 u_0 + a_1 \pmod{\mathrm{lcm}(p_1,p_2)} \] 这样我们就合并了两个式子,依此类推可以解决所有的式子。

板子题:P4777 【模板】扩展中国剩余定理(EXCRT)

时间复杂度 \(\mathcal{O}(n \log V)\)

代码:

// 2024年02月09日 03:38:48
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e5 + 15))

int exgcd(int a, int b, int &x, int &y)
{
    int d = a;
    if(!b) { x = 1, y = 0; }
    else { d = exgcd(b, a % b, y, x), y -= a / b * x;}
    return d;
}
int a[N], p[N];
int ExCRT(int n)
{
    int u, v, p1 = p[1], res = a[1];
    for(int i = 2; i <= n; i++)
    {
        int p2 = p[i], c = (a[i] - res % p2 + p2) % p2;
        int g = exgcd(p1, p2, u, v); assert(c % g == 0);
        int l = p2 / g; u = (__int128_t) u * (c / g) % l;
        res += u * p1; p1 *= l; res = (res % p1 + p1) % p1;
    }
    return (res % p1 + p1) % p1;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n; cin >> n;
    for(int i = 1; i <= n; i++) cin >> p[i] >> a[i];
    cout << ExCRT(n) << '\n';
    return 0;
}

莫比乌斯函数

\(\mu\) 为莫比乌斯函数,定义为 \[ \begin{aligned} \mu(n) = \begin{cases} 1,&n=1\\[8pt] (-1)^k,&k\text{ 为 }n \text{ 本质不同质因子个数}\\[8pt] 0,&n\text{含有平方因子(其实就是剩余的情况)} \end{cases} \end{aligned} \]

代码求解

线性筛 \(\mathcal{O}(n)\)\(\mu\)

// 2023年07月04日 20:43:15
void Mobius(int n = N - 10)
{
    mu[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        if(!ck[i]) { prime[++pcnt] = i; mu[i] = -1; }
        for(int j = 1; j <= pcnt && i * prime[j] <= n; j++)
        {
            int pos = i * prime[j]; ck[pos] = true;
            if(i % prime[j]) { mu[pos] = -mu[i]; } else { mu[pos] = 0; break; }
        }
    }
}

莫比乌斯反演

\[ \sum_{d\mid \gcd(i,j)}\mu(d)=[\gcd(i,j)=1]=[i\perp j] \]

应用

一个小转化(仅改变这两个相关和式,左侧其他的 \(\Sigma\) 不变) \[ \sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=k] =\sum_{i=1}^{\left\lfloor\frac{n}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{k}\right\rfloor}[\gcd(i,j)=1] \]\(d(x)\)\(x\) 的约数个数,则有 \[ d(ij)=\sum_{x\mid i}\sum_{y \mid j}[\gcd(x,y)=1] \]


拉格朗日定理

\(p\) 为素数,对于模 \(p\) 意义下的整系数多项式 \[ f(x) = \sum_{n\ge 0}a_nx^n,p\nmid a_n \] 的同余方程 \(f(x) \equiv 0 \pmod{p}\) 在模 \(p\) 意义下至多有 \(n\) 个不同解

应用

关于同余方程的引理

对于任意 \(a\) ,至多有 \(n\) 个不同的 \(x\) 满足同余方程 \(nx \equiv a \pmod{m}\)

应用于抽象代数的定理中

在有限可交换群 \(G\) 中,以下两个条件等价:

\(G\) 是循环群。

对于任意一个元素 \(a\) ,至多有 \(n\) 个不同的元素 \(x\) 满足条件 \(x^n=a\)

结论:对于素数 \(p\) ,模 \(p\) 的简化剩余系 \(Z_p^*\) 对于乘法构成的群是循环群


原根

:满足同余式 \(a^n \equiv 1 \pmod{m}\) 的最小正整数 \(n\) 存在,这个 \(n\) 称作 \(a\)\(m\) 的阶,记作 \(\delta_m(a)\)

在抽象代数中,这里的“阶”就是模 \(m\) 缩剩余系关于乘法形成的群中,元素 \(a\) 的阶。记号 \(\delta\) 表示阶也只用于这个特殊的群。

下面的诸多性质可以直接扩展到抽象代数中阶的性质。

阶的性质

  1. \(a,a^2,\dots,a^{\delta_m(a)}\)\(m\) 两两不同余

  2. \(a^n \equiv 1 \pmod{m}\) ,则 \(\delta_m(a) \mid n\)

  3. \(a^p \equiv a^q \pmod{m}\) ,则有 \(p\equiv q \pmod{\delta_m(a)}\)

  4. \(m \in \mathbb{N}^*,a,b \in \mathbb{Z} ,\gcd(a,m)=\gcd(b,m)=1\) ,则 \[ \delta_m(ab)=\delta_m(a)\delta_m(b) \] 的充分必要条件是 \[ \gcd(\delta_m(a),\delta_m(b))=1 \]

  5. \(k\in \mathbb{N},m\in \mathbb{N}^*,a\in\mathbb{Z} ,\gcd(a,m)=1\) ,则 \[ \delta_m(a^k)=\dfrac{\delta_m(a)}{\gcd(\delta_m(a),k)} \]

原根:设 $m^*,a $ 若 \(\gcd(a,m)=1\) ,且 \(\delta_m(a) = \varphi(m)\) ,则称 \(a\) 为模 \(m\) 的原根

在抽象代数中,原根就是循环群的生成元。这个概念只在模 \(m\) 缩剩余系关于乘法形成的群中有“原根”这个名字,在一般的循环群中都称作“生成元”。

并非每个模 \(m\) 缩剩余系关于乘法形成的群都是循环群,存在原根就表明它同构于循环群,如果不存在原根就表明不同构。

原根判定定理:设 \(m\ge 3,\gcd(a,m)=1\) ,则 \(a\) 是模 \(m\) 的原根的充要条件是,对于 \(\varphi(m)\) 的每个素因数 \(p\) ,都有 \(a^{\frac{\varphi(m)}{p}}\not\equiv 1 \pmod{m}\)

原根个数:若一个数 \(m\) 有原根,则它的原根个数为 \(\varphi(\varphi(m))\)

原根存在定理:一个数 \(m\) 存在原根当且仅当 \(m=2,4,p^\alpha,2p^\alpha\) ,其中 \(p\) 为奇素数,\(\alpha \in \mathbb{N}^*\)

  • 定理1:对于奇素数 \(p\)\(p\) 有原根
  • 定理2:对于奇素数 \(p\)\(\alpha \in \mathbb{N}^*\)\(p^\alpha\) 有原根
  • 定理3:对于奇素数 \(p\)\(\alpha\in\mathbb{N}^*\)\(2p^\alpha\) 的原根存在
  • 定理4:对于 \(m\ne2,4\) ,且不存在奇素数 \(p\)\(\alpha \in \mathbb{N}^*\) 使得 \(m=p^\alpha,2p^\alpha\) ,模 \(m\) 的原根不存在

二次剩余

对于二次同余方程 \(x^2\equiv n \pmod{p}\) 有解,则称 \(n\)\(p\) 的二次剩余,\(x\) 为该二次同余方程的解

二次剩余 \(n\) 就是一个二次项 \(\bmod p\) 后的剩余,\(n\) 不可以是 \(p\) 的倍数

Legendre 符号(中间那个发音是g不是j) \[ \left(\dfrac{a}{p}\right)=\begin{cases} 1,&p\nmid a \text{ 且 }a \text{ 是模 }p \text{ 的二次剩余} , \\-1,&p\nmid a \text{ 且 }a \text{ 不是模 }p \text{ 的二次剩余} , \\0,&p\mid a. \end{cases} \] Legendre 符号为完全积性函数

Euler 判别准则

对于奇素数 \[ a^{\frac{p-1}{2}} \equiv \left(\dfrac{a}{p}\right)\equiv\begin{cases} 1 \pmod{p}, \text{ 若 }x^2 \equiv a \pmod{p} \text{ 有解}, \\\\-1 \pmod{p}, \text{ 若 }x^2 \equiv a \pmod{p} \text{ 无解}. \end{cases} \]

引理:令 \(p\) 为素数和模 \(p\) 意义下原根 \(g\) 并令 \(a\equiv g^k \pmod{p}\) ,那么 \(x^2 \equiv a \pmod{p}\) 有解当且仅当 \(k\) 为偶数

二次剩余和二次非剩余的数量

对于奇素数 \(p\) 和集合 \(\{1,2,\dots,p-1\}\) ,在模 \(p\) 意义下二次剩余的数量等于二次非剩余的数量

引理:对于 \(d \mid (p-1)\) 和奇素数 $p $ ,\(x^d \equiv 1 \pmod{p}\) 恰有 \(d\) 个解


参考文献

[1] https://oi-wiki.org/math/number-theory/inverse/


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录