数论笔记

  • 本笔记结合徐骁扬学长的讲课和CM数学课

  • 题单:CM数学课题单

    注:勾选框表示题目

因数相关

结论
  • \(1\sim n\)的所有数的因数个数一共有\(O(n\log n)\),即\(\sum\limits_{i=1}^nd(i)=O(n\log n)\)

    证明:

    • \(\sum\limits_{i=1}^nd(i)=\sum\limits_{i=1}^n\sum\limits_{j\mid i}1=\sum\limits_{j=1}^n\sum\limits_{j\mid i\land 1\leq i\leq n}1=\sum\limits_{j=1}^n\lfloor\frac{n}{j}\rfloor\leq\sum\limits_{j=1}^n\frac{n}{j}=n\ln n\)
  • 质数定理:\(1\sim n\)中质数个数为\(O(\frac{n}{\log n})\)

  • 伯特兰-切比雪夫定理:\(n\geq 1\)\(n\sim 2n\)中至少有一个素数

  • 直角三角形边长通式:\(a=w\cdot2uv,b=w\cdot(u^2-v^2),c=w\cdot(u^2+v^2)\),其中\(u,v,w\in\mathbb{Z^+}\)

题目
    • 问题转化:找到\(x\)使得\(a_1,a_2,\cdots,a_n\)中至少有2个数是x的倍数

    • 做法:

      预处理\(1\sim10^6\)数的所有因数,扫过每一个\(a_i\)(可以去重以保证复杂度),把cnt[a_i的一个因数]++,找到最大的\(x\)使cnt[x]\(\geq2\)

    • 观察:记\(\gcd(a_i+y,a_2+y,\cdots,a_n+y)=g_y\),则\(g_y\mid(a_i-a_j),1\leq i,j\leq n\)

      所以,答案最大为\(g=\gcd\limits_{1\leq i,j\leq n\land i\neq j}(a_i-a_j)\)

      想要答案达到最大,发现\(a_i\equiv t\pmod g,1\leq i\leq n\),则让所有数加上\(-t\bmod g\)即可

      快速计算\(g\):直接算\(g=\gcd\limits_{1\leq i\leq n-1}(a_{i+1}-a_i)\)

最大公约数相关

GCD

常用公式
  • \(\gcd(a,b)=\gcd(a,a+b)=\gcd(a,b-a)=\gcd(a,b\bmod a)=\gcd(b,a\bmod b)\)

  • \(\gcd(ab,ac)=a\cdot \gcd(b,c)\)

  • \(\gcd(a,b)\cdot\mathrm{lcm}(a,b)=a\cdot b\)

结论
  • \(\gcd(a_1,a_2,\cdots,a_n)=g\),则\(\{a_1,a_2,\cdots,a_n\}\)的公因子等价于\(g\)的因子
辗转相除法
  • 有式子\(\gcd(a,b)=\gcd(b,a\mod b)\),直到\(b=0\)\(\gcd=a\)
实现
Type gcd(Type a,Type b){
	return (y==0)?x:gcd(y,x%y);
}
  • 复杂度分析:

    发现,每递归一层\(\mathrm{l_2}a+\mathrm{l_2}b\)严格变小,于是复杂度是\(O(\log n)\)(规定\(\mathrm{l_2}\)表示一个数的二进制位数)

    证明:

    1. \(\mathrm{l_2}a=\mathrm{l_2}b\),则两个数的二进制的第一位都为1,做一次后\(a\bmod b\)的二进制为至少少1
    2. \(\mathrm{l_2}a>\mathrm{l_2}b\),则\(a\bmod b\)一定比a小。

裴蜀定理

  • 描述1:对于不定方程\(ax+by=c\),有整数解当且仅当\(\gcd(a,b)\mid c\)
  • 描述2:\(a,b\)是不全为0的整数,则\(\exists x,y\),使\(ax+by=\gcd(a,b)\)
  • 证明:按exGCD的方法递归构造即可
拓展
  • \(\gcd(a_1,a_2,\cdots,a_n)=1\),则每个数\(N\)都可以表示为\(\{a_i\}\)的线性组合。

  • 加强形式:若\(\gcd(a_1,a_2,\cdots,a_n)=g\),则每\(g\)的倍数\(N\)都可以表示为\(\{a_i\}\)的线性组合。

    • 证明,归纳法:

      1. \(n=1\)时,显然成立

      2. \(n=2\)时,是裴蜀定理

      3. \(n>2\)时,取\(b=\gcd(a_1,a_2,\cdots,a_{n-1})\),则\(g=\gcd(b,g_n)\)

        根据裴蜀定理\(g=bx+a_ny\),则\(g\)的倍数都可以被表示出。

  • 非负版本:充分大的正数,可以表示为\({a_i}\)的非负线性组合;其界可有同余最短路求出(?)。

exGCD

做法

对于方程\(ax+by=\gcd(a,b)\)

根据\(\gcd(a,b)=\gcd(b,a\mod b)\)写出同形式方程\(bx'+(a\mod b)y'=\gcd(b,a\mod b)\)

所以有:\(ax+by=bx'+(a-b*\lfloor\frac{a}{b}\rfloor)y'\)

化简:\(a(x-y')+b(y-x'+\lfloor\frac{a}{b}\rfloor*y')=0\)

其中一组可行解:\(\begin{cases} x=y'\\ y=x'-\lfloor\frac{a}{b}\rfloor*y' \end{cases}\)

可以递归的做,直到\(b=0\)时,\(a_tx_t+b_ty_t=\gcd(a_t,b_t)=a_t\)

此时的解:\(\begin{cases} x_t=1\\ y_t=任意值 \end{cases}\)

  • 注意:当\(a,b\)有一个时负数时,不应该取\(\lfloor\frac{a}{b}\rfloor\),而是\(\lceil\frac{a}{b}\rceil\),即c++自带的向0取整

    //验证程序
    int a=1213121321,b=3123;
    for(int i=0;i<=1;i++){
        for(int j=0;j<=1;j++){
            int aa=a*(i==0?1:-1),bb=b*(j==0?1:-1);
            printf("%d%%%d=%d\n",aa,bb,aa%bb); 
            printf("%d-[%d]*%d=%d\n",aa,aa/bb,bb,aa-aa/bb*bb);
            printf("%d-d%dd*%d=%d\n",aa,(int)floor(1.0*aa/bb),bb,aa-((int)floor(1.0*aa/bb))*bb);
            printf("%d-u%du*%d=%d\n",aa,(int)ceil(1.0*aa/bb),bb,aa-((int)ceil(1.0*aa/bb))*bb);
            printf("--------------\n");
        }
    }
    
  • :用exgcd求出的解一定有\(|x|\leq b,|y|\leq a\)

实现
  • 递归版

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

不定方程

求解\(ax\equiv 1(\mod b)\),相当于求\(ax+by=1\)的解,使用exgcd

  • 注意:根据裴蜀定理,有解时\(\gcd(a,b)=1\),但题目保证有解,即\(a,b\)一定互质

求出特解\((x_0,y_0)\)后,任意解可以为\((x_0+k\cdot b,y_0-k\cdot a)\),其中\(k\in \mathbb{Z}\)

  • 推导1:
  1. 根据裴蜀定理判无解

  2. 先求出\(ax+by=\gcd(a,b)\)的一组解\((x_g,y_g)\),然后同时乘以\(\frac{c}{\gcd(a,b)}\)得到原方程的一组解\((x_0,y_0)=(x_g\cdot \frac{c}{\gcd(a,b)},y_g\cdot \frac{c}{\gcd(a,b)})\)

  3. 若改变解\((x_0,y_0)\to (x_0+d_x,y_0-d_y)\)也使方程成立,即\(a(x_g\cdot \frac{c}{\gcd(a,b)}+d_x)+b(y_g\cdot \frac{c}{\gcd(a,b)}-d_y)=c\)

    化简:\(x_g\cdot \frac{b\cdot c}{\gcd(a,b)}+a\cdot d_x+y_g\cdot \frac{a\cdot c}{\gcd(a,b)}-b\cdot d_y=c\)

    有:\(a\cdot d_x=b\cdot d_y\)

    要使每次的增减量最小且为整数,则\(d_{x_{min}}=\frac{b}{\gcd(a,b)},d_{y_{min}}=\frac{a}{\gcd(a,b)}\)

  4. 然后据此计算出\(x\)的最小正整数值及对应的\(y\),和\(y\)的最小正整数值及对应的\(x\),即可

  • 推导2:
  1. 判无解后,如果\(\gcd(a,b)>1\),则将方程两边除掉\(\gcd(a,b)\),方程变为\(\frac{a}{\gcd(a,b)}x+\frac{b}{\gcd(a,b)}y=\frac{c}{\gcd(a,b)}\),记为\(a'x+b'y=c'\)
  2. 用exGCD找到\(a'x+b'y=1\)的一组特解\((x',y')\),则原解为\(a'(c‘x')+b'(c’y')=c'\),记为\(a'x_0+b'y_0=c’\)
  3. 此时方程的通解为\(\begin{cases} x=x_0+b't\\ y=y_0-a't \end{cases}\),其中\(t\in\mathbb{Z}\)
    • 验证其是解:\(a'(x_0+b't)+b'(y_0-a't)=ax_0+by_0=c'\)
    • 证明未漏掉解:
      • \(a'x+b'y=a'x_0+b'y_0\)
      • 移项\(a'(x-x_0)=b'(y_0-y)\)
      • 由于\(a\perp b\),则\(b\mid x-x_0,a\mid y_0-y\),即\(x\)\(x_0\)的差是\(b\)的倍数,\(y\)\(y_0\)的差是\(a\)的倍数,通解形式正确
  4. 带回\(a,b,c\),得\(\begin{cases} x=\frac{c}{\gcd(a,b)}x'+\frac{b}{\gcd(a,b)}t\\ y=\frac{c}{\gcd(a,b)}y'-\frac{a}{\gcd(a,b)}t \end{cases}\)
  • 描述:有两个正整数\(a,b\)\(a\perp b\),要找到最小的\(N\),使得\(ax+by\)不能表示出\(N\)\(a,b\geq0\)

  • 如果\(x,y\)无限制,根据裴蜀定理,任何整数都一定可以被表示。

  • 答案:\(N=ab-a-b=(a-1)(b-1)-1\)

    • 证明:
    1. \(N\)无法被表示

      假设\(N\)可以被表示

      \(N=ax+by\),其中\(a,b\geq0\),则\(ab-a-b=ax+by\),则\(ab=a(x+1)+b(y+1)\)

      由于\(a\perp b\),得\(b\mid x+1,a\mid y+1\),所以\(x+1\geq b,y+1\geq a\)

      因此\(a(x+1)+b(y+1)\geq2ab\),矛盾!

    2. \(>N\)的数都可以被表示

      \(n\)\(>N\)的一个数,先找到一组整数解\(ax_0+by_0=n\),满足\(y_0\in[0,a-1]\)

      \(ax_0=n-by_0>ab-a-b-by_0\geq ab-a-b-b(a-1)=-a\),所以得到\(x_0>-1\),即\(x_0\geq0\),得证。

  • 相关结论

    1. \(n\in[0,N]\)时,\(n\)\(N-n\)恰好有一个可以被表示。

      • 证明:

        1. 不可能两个都被表示,否则\(N=n+(N-n)\)就可以被表示了

        2. \(n\)不可被表示,求证\(N-n\)可以被表示

          \(n=ax_0+by_0\),若\(0\leq y_0\leq a-1\),则有\(x_0<0\)

          然后有\(N-n=ab-a-b-ax_0-by_0=a(-x_0-1)+b(a-1-y_0)\),其中\(a-1-y0\geq0,-x0-1>1\),得证。

多元不定方程
  • 转化:\(a_1x_1+a_2x_2+\cdots+a_nx_n=p(-k)+b\),记\(a_{n+1}=p,x_n+1=k\),则\(a_1x_1+a_2x_2+\cdots+a_{n+1}x_{n+1}=b\)

  • 根据裴蜀定理加强版,有解时有\(\gcd(a_1,a_2,\cdots,a_{n+1})\mid b\)

  • 于是先把原式除掉\(\gcd(a_1,a_2,\cdots,a_{n+1})\mid b\),记作\(a_1'x_1+a_2'x_2+\cdots+a_{n+1}'x_{n+1}=b'\)

  • 递归的把它做成一个\(n=2\)的情况:

    \(a_1'x_1+a_2'x_2+\cdots+a_n'x_n=\gcd(a_1,a_2,\cdots,a_n)X\),则须求解\(\gcd(a_1,a_2,\cdots,a_n)X+a_{n+1}x_{n+1}=b\),然后递归即可。

同余相关

同余类与缩同余类

  • \(m\)的同余类:\(\mathbb{Z}_m=\{\overline0,\overline1,\cdots,\overline{m-1}\}\)其是一个群
  • \(m\)的缩同余类:\(\mathbb{Z}_m^*=\{\overline x\mid x<x<m,\gcd(x,m)=1\}\)其关于乘法封闭

模意义下的乘法逆元

  • \(a\in\mathbb{Z}_m^*\space(\gcd(a,m)=1)\),则\(\exists b\in\mathbb{Z}_m^*\)\(a\cdot b=1\pmod m\)

  • 证明:转换成exGCD即可

  • 以下的\(p\)表示模数

  • \(a\)\(\mod p\)意义下的逆元存在,当且仅当\(p\perp a\)

法1:费马小定理求逆元
  • 定理:\(a^{p-1}\equiv 1(\mod p)\),其中\(p\)为质数,\(p\perp a\)

    那么\(a^{-1}\equiv a^{p-2}(\mod p)\)

  • 注意:仅限于模数为质数的时候

  • 【补充】欧拉定理:\(a^{\varphi(p)}\equiv 1(\mod p)\)只需要满足\(p\perp a\)

long long inverse(long long x,long long MOD){
	return quickpow(x,MOD-2ll,MOD);
}
法2:exGCD求逆元
  • 解同余方程\(a\cdot x\equiv 1(\mod p)\),其中\(x=a^{-1}\)只需要满足\(\gcd(a,p)=1\)
long long inverse(long long a,long long MOD){
    long long res,_y;
    exgcd(a,MOD,res,_y);
    while(res<0)res+=MOD;
    while(res>=MOD)res-=MOD;
    return res;
}
法3:阶乘求逆元
  • 此方法为\(O(n+logV)\)求出前\(n\)个数的逆元,并且需要模数为质数
  • 求出\(fac[i]=i!\),然后用前两种方法求出\(fac[n]\)的逆元\(invfac[n]\)
  • 倒序递推:\(invfac[i]=invfac[i+1]*(i+1)\)\(inv[i+1]=invfac[i+1]*fac[i]\)
long long inv[N],invfac[N],fac[N];
void inverse_n(long long n,long long MOD){
	fac[0]=1;
	for(long long i=1;i<=n;i++){
		fac[i]=((__int128)1)*fac[i-1]*i%MOD;
	}
	invfac[n]=inverse(fac[n],MOD);//建议用exGCD
	for(long long i=n-1;i>=0;i--){
		invfac[i]=((__int128)1)*invfac[i+1]*(i+1)%MOD;
		inv[i+1]=((__int128)1)*invfac[i+1]*fac[i]%MOD;
	}
	return ;
}
法4:线性递推求逆元
  • 需要模数为质数

  • 边界:\(1^{-1}\equiv 1(\mod p)\)

  • \(p=i\cdot s+t\),则\(s=\lfloor\frac{p}{i}\rfloor,t=p\mod i\)

    由于\(p=i\cdot s+t\equiv0(\mod p)\)

    两边同时乘以\(i^{-1}t^{-1}\),并移项得:\(i^{-1}\equiv -s\cdot t^{-1}(\mod p)\)

    因此得到递推式:\(i^{-1}\equiv \lfloor\frac{p}{i}\rfloor\cdot \Big(p-(p \mod i)^{-1}\Big)(\mod p)\)(用\(p-\dots\)防止负数出现)

long long inv[N];
void inverse_n(long long SIZE,long long MOD){
	inv[1]=1;
	for(int i=2;i<=SIZE;i++){
		inv[i]=((__int128)1)*inv[MOD%i]*(MOD-MOD/i)%MOD;
	}
}
求任意n个整数的逆元
  • 类似阶乘求逆元,\(O(n+logV)\)求出任意n个整数的逆元
  • 求出数的前缀乘积\(sum[i]=\prod\limits_{j=1}^ival[i]\),然后用前两种方法求出\(sum[n]\)的逆元\(invsum[n]\)
  • 倒序递推:\(invsum[i]=invsum[i+1]*(i+1)\)\(inv[i+1]=invsum[i+1]*sum[i]\)
  • 考虑\(K<N\)的情况,否则\(K=N*d+K'\),让序列中所有元素加上\(d\)即可。

    现在需要的到一个其中有\(K\)个1,其他是0的序列满足条件。

  • \(L=K^{-1}\pmod N\),则把\(S_0,S_L,S_{2l},\cdots,S_{(K-1)L}\)的位置设为0(第0位表示第\(N\)位),可以发现这些位置互不相同(\(K\perp N\))。

  • 原来的操作让\(S_0\)变为0,让\(S_1(S_{KL})\)变为1,满足循环同构的条件

中国剩余定理CRT

  • 找到同余方程组\(x\equiv a_i(\mod p_i)\)的解,满足所有模数\(p_i\)互质

  • 一个思路是,从零开始加,加的数不会影响其他同余方程的结果,只会让某一个同余方程的结果加1

  • 可以发现\(d_i=\prod\limits_{j=1}^n[j\not=i]p_j\),其中\(d_i\not\equiv0(\mod p_i)\land d_i\equiv0(\mod p_j,j\not=i)\)

  • 因此,需要只让一个同余方程结果加1可以加\(d_i\cdot\Big(d_i^{-1}(\mod p_i)\Big)\)

  • 最终答案为\(\sum\limits_{i=1}^na_i\cdot d_i\cdot\Big(d_i^{-1}(\mod p_i)\Big)\)

  • 答案任意\(\pm k\cdot\mathop{\text{lcm}}\limits_{i=1}^np_i\)也满足条件

exCRT

  • 对于\(p_i\)不互质的情况,考虑两两合并同余方程

  • 对于两个同余方程\(\begin{cases}x\equiv a_i(\mod p_i)\\x\equiv a_j(\mod p_j)\end{cases}\),可以写作\(\begin{cases}x+k_i\cdot p_i=a_i\\x+k_j\cdot p_j=a_j\end{cases}\),消去\(x\)\(k_i\cdot p_i-k_j\cdot p_j=a_i-a_j\)

  • 用exGCD可以求出\(k_i\)\(k_j\)即可求出共同的解\(x\equiv h(\mod \text{lcm}(p_i,p_j))\)

补充
  • 若同余方程有系数,如\(b_ix\equiv a_i(\mod p_i)\),我们把它写作不定方程\(b_ix+p_ik=a_i\)

  • 根据裴蜀定理:如果\(\gcd(b_i,p_i)\nmid a_i\),则无解;

    否则,先用exGCD解出\(b_ix+p_ik=gcd(b_i,p_i)\)的一组特解\(x_0\),同二元一次不定方程的解法,通解\(x=x_0\cdot \frac{a_i}{\gcd(b_i,p_i)}+any\cdot\frac{p_i}{\gcd(b_i,p_i)}\)

  • 于是就得到了系数为\(1\)的同余方程:\(x=x_0\cdot \frac{a_i}{\gcd(b_i,p_i)}\pmod{\frac{p_i}{\gcd(b_i,p_i)}}\),然后用exCRT合并。

BSGS

  • 描述:求解\(a^x\equiv b\pmod p\)的最小解,其中\(a\perp p\),也就是模意义下的对数(离散对数)。

  • 根据欧拉定理,有解则解一定\(\leq \varphi(p)\),于是把式子写作\(a^{qB+r}\equiv b\pmod p\),其中\(B=\lceil\sqrt{\varphi(p)}\rceil\)\(r<B\)

    由于\(a\perp p\),式子可以改为\((a^{B})^{q}\equiv b\cdot (a^{-1})^{r}\pmod p\),处理出同余式两边的值,查询是否有相等的,即可找到答案。

  • 注意:查询相等时,用哈希表把\((a^{-1})^r\)做键,\(r\)做值,此时键会重复,要取最小的一个,要特判!!

    hack:5598755 2642091 857926

exBSGS

  • 要求离散对数,但是不满足互质条件,无法求逆元。

  • 对于原方程\(a^x\equiv b\pmod p\),考虑构造\(a\perp p\)的情况。

    \(g=\gcd(a,p)\),如果\(g\nmid b\),则说明无解;

    否则,两边同时除以\(g\)\(a^{x-1}\cdot\frac{a}{g}\equiv\frac{b}{g}\pmod{\frac{p}{g}}\)

    然后,现在\(\frac{a}{g}\perp \frac{p}{g}\)了,把它挪到右边:\(a^{x-1}\equiv\frac{b}{g}\cdot(\frac{a}{g})^{-1}\pmod{\frac{p}{g}}\)注意:要在最后求\(\prod \frac{a}{g_i}\)逆元;

    但是\(a\)\(\frac{p}{g}\)不一定互质,递归继续做。

  • 考虑到\(g\geq2\),所以每次至少让\(p\)变为一半,至多做\(O(\log_2p)\)次,做完后再用普通BSGS做即可。

    注意:不能保证答案\(>\log_2p\),所以还要枚举\(i=0\sim\log_2p\),验证\(a^i\bmod p\)是否为\(b\)

积性函数相关

求解一般积性函数前n项函数值方法

积性函数
  • 一个积性函数\(f(x)\)满足:\(f(ab)=f(a)\cdot f(b)\)其中\(a\perp b\)\(a,b\)互质)
求法(线性筛)
  • 需要知道\(f(1)\)的值

  • 质数求法:对于一个质数\(p\),需要知道如何求\(f(p)\)的值

  • 递推求法:对于\(p^k\),其中p是质数,需要知道如何用\(f(p^k)\)\(f(p^{k-1})\)的递推关系求值

  • 在筛法过程中,记录数\(x\)的最小质因子\(p\)\(x\)中的次方值\(val[x]=p^k\)

  1. \(x\)是质数时,用质数求法

  2. 枚举质数\(p_i\)

    • 如果\(p_i\perp x\),则根据积性函数性质\(f(x\cdot p_i)=f(x)\cdot f(p_i)\);此时\(val[x\cdot p_i]=p_i\)

    • 如果\(p_i\mid x\),此时\(val[x*p_i]=p_i*val[x]\)

      • \(x=p_i^k\),则用递推求法\(f(x)\)\(f(p_i^k)\))推到\(f(x*p_i)\)\(f(p_i^{k+1})\)

      • 否则\(f(x*p_i)=f(\frac{x}{val[x]})*f(val[x]*p_i)\)(保证互质才能使用积性函数的性质)

  • 可能要预处理一些值

\(\sigma_d(x)\)的代码:

long long d,f[N],val[N];//f:\sigma_d
bitset<N>book;
vector<pair<int,long long>>pr;
void euler(int n){
	book[0]=book[1]=1;
	f[0]=0,f[1]=1;
	for(int i=2;i<=n;i++){
		if(!book[i]){
			pr.emplace_back(i,quickpow(i,d));
			f[i]=quickpow(i,d)+1;
			val[i]=i;
		}
		for(auto v:pr){
			if(1ll*i*v.first>n)break;
			book[i*v.first]=1;
			if(i%v.first==0){
				val[i*v.first]=val[i]*v.first;
				if(i==val[i])
					f[i*v.first]=f[i]*v.second+1;
				else
					f[i*v.first]=f[i/val[i]]*f[val[i]*v.first];
				break;
			}
			else{
				val[i*v.first]=v.first;
				f[i*v.first]=f[i]*f[v.first];
			} 
		}
	}
}

  • lucas性质\(C(m,n)\mod 2\equiv [(n\&m)=1]\)??
posted @ 2025-07-09 18:15  mike_666  阅读(15)  评论(0)    收藏  举报