【学习笔记】数学知识-同余

同余

  • 取模运算性质
    • \((a+b) \bmod p=((a \bmod p)+(b \bmod p)) \bmod p\)
    • \((a-b) \bmod p=((a \bmod p)-(b \bmod p)) \bmod p\)
    • \((a \times b) \bmod p=((a \bmod p) \times (b \bmod p)) \bmod p\)
    • 引流两篇讲解负数取模的文章 link1 | link2
  • 若整数 \(a\) 和整数 \(b\) 除以正整数 \(m\) 的余数相等,则称 \(a,b\)\(m\) 同余,记为 \(a \equiv b \pmod{m}\) ;否则,称 \(a,b\)\(m\) 不同余,记为 \(a \not\equiv b \pmod{m}\)
    • 性质
      • 自反性: \(a \equiv a \pmod{p}\)
      • 对称性:若 \(a \equiv b \pmod{p}\) ,则 \(b \equiv a \pmod{p}\)
      • 传递性:若 \(a \equiv b \pmod{p},b \equiv c \pmod{p}\) ,则 \(a \equiv c \pmod{p}\) ;若 \(a \equiv b \pmod{p},q|p\) ,则 \(a \equiv b \pmod{q}\)
      • 同加性:若 \(a \equiv b \pmod{p}\) ,则 \(a+c \equiv b+c \pmod{p},a-c \equiv b-c \pmod{p}\)
      • 同乘性:若 \(a \equiv b \pmod{p}\) ,则 \(a \times c \equiv b \times c \pmod{p}\)
      • \(ac \equiv bc \pmod{p}\) ,则 \(a \equiv b \pmod{\dfrac{p}{\gcd(c,p)}}\)
      • 同幂性:若 \(a \equiv b \pmod{p}\) ,则 \(a^n \equiv b^n\pmod{p}\)
      • \(a \equiv b \pmod{p},a \equiv b \pmod{q}\) ,则 \(a \equiv b \pmod{\operatorname{lcm}(p,q)}\)
      • \(a \equiv b \pmod{p}\) ,则 \(p|(a-b)\)
  • 同余类
    • 对于 \(\forall a \in[0,p-1]\) ,集合 \(\{a+kp\}(k \in \mathbb{Z})\) 的所有数模 \(p\) 同余,余数都为 \(a\) 。该集合称为一个模 \(p\) 的同余类,简记为 \(\overline{a}\)
  • 剩余系
    • \(p\) 的同余类一共有 \(p\) 个,分别为 \(\overline{0},\overline{1},\overline{2}, \dots ,\overline{p-1}\) 。它们构成 \(p\) 的完全剩余系。
    • \(1 \sim p\) 中与 \(p\) 互质的数代表的同余类共有 \(\varphi(p)\) 个,它们构成 \(p\) 的简化剩余系。
      • \(p\) 的简化剩余系中的数满足与 \(p\) 互质且模 \(p\) 互不相同。
    • 性质
      • 若整数 \(a,b(1\le a,b\le p),p\) 满足 \(\gcd(a,p)= \gcd(b,p)=1\) ,有 \(a,b,(a \times b) \bmod p\) 属于 \(p\) 的简化剩余系。
      • 若整数 \(a,b,x,p\) 满足 \(\gcd(a,p)=1\) ,则当 \(x\) 跑遍模 \(p\) 的简化剩余系时, \(ax\) 也跑遍模 \(p\) 的简化剩余系;当 \(x\) 跑遍模 \(p\) 的完全剩余系时, \(ax\) 也跑遍模 \(p\) 的完全剩余系;当 \(x\) 跑遍模 \(p\) 的完全剩余系时, \(ax+b\) 也跑遍模 \(p\) 的完全剩余系。

费马小定理

  • 费马小定理:若 \(p\) 是质数,则对于任意整数 \(a\) ,有 \(a^p \equiv a \pmod{p}\)
    • 证明
      • \(a \bmod p=0\) 时,显然结论成立。
      • \(a \bmod p \ne 0\) 时,不存在一组 \(x,y\) 满足 \(1 \le x,y<p,xa \equiv ya \pmod{p}\) 。因此 \(1 \sim p-1\) 所有数,乘以 \(a\) 之后对 \(p\) 取模,仍可得 \(1 \sim p-1\) 所有数。即 \(\prod\limits_{i=1}^{p-1} i \equiv \prod\limits_{i=1}^{p-1} ai \pmod{p}\) ,易知其中 \(\prod\limits_{i=1}^{p-1} i\)\(p\) 互质,则 \(\prod\limits_{i=1}^{p-1}a \equiv 1 \pmod{p}\) ,即 \(a^{p-1} \equiv 1 \pmod{p}\) 。等式两边同乘 \(a\) ,得到 \(a^p \equiv a \pmod{p}\)
  • 变形
    • \(p\) 是质数,则对于任意整数 \(a\) ,有 \(a^{p-1} \equiv \begin{cases}0&a \bmod p=0\\1&a \bmod p \ne 0\end{cases} \pmod{p}\)

欧拉定理

  • 欧拉定理:若正整数 \(a,p\) 满足 \(\gcd(a,p)=1\) ,则 \(a^{\varphi(p)} \equiv 1 \pmod{p}\)
  • 证明
    • \(p\) 为质数时,有 \(a^{\varphi(p)}=a^{p-1}\) ,依据费马小定理,有 \(a^p \equiv a \pmod{p}\) ,故 \(a^{p-1} \equiv 1 \pmod{p}\)
    • \(p\) 不为质数时,设 \(S=\{ p_1,p_2, \dots ,p_{\varphi(p)}\}\)\(p\) 的简化剩余系,对于任意一对 \(i,j(1 \le i,j \le \varphi(p),i \ne j)\) ,有 \((a \times p_i) \bmod p \ne (a \times p_j) \bmod p\) ,且 \(a \times p_i,a \times p_j\) 均与 \(p\) 互质。因此 \(S\) 中所有数,乘以 \(a\) 之后对 \(p\) 取模,仍可得 \(S\) 中所有数,则 \(\prod\limits_{i=1}^{\varphi(p)} p_i \equiv \prod\limits_{i=1}^{\varphi(p)} ap_i \pmod{p}\) ,易知其中 \(\prod\limits_{i=1}^{\varphi(p)} p_i\)\(p\) 互质,即 \(\prod\limits_{i=1}^{\varphi(p)}a \equiv 1 \pmod{p}\) ,即 \(a^{\varphi(p)} \equiv 1 \pmod{p}\)
  • 应用
    • 若正整数 \(a,p\) 满足 \(\gcd(a,p)=1\) ,则满足 \(a^x \equiv 1 \pmod{p}\) 的最小正整数 \(x_0\) 满足 \(x_0|\varphi(p)\)
      • 证明
        • 考虑反证法。假设满足 \(a^x \equiv 1 \pmod{p}\) 的最小正整数 \(x_0\) 不满足 \(x_0|\varphi(p)\) 。设 \(\varphi(p)=qx_0+r(0<r<x_0)\) 。因为 \(a^{x_0} \equiv 1 \pmod{p}\) ,所以 \(a^{qx_0} \equiv 1 \pmod{p}\) 。根据欧拉定理,有 \(a^{\varphi(p)} \equiv 1 \pmod{p}\) ,所以 \(a^r \equiv 1 \pmod{p}\) 。这与 \(x_0\) 最小矛盾。因此假设不成立,故 \(x_0|\varphi(p)\)
    • 若正整数 \(a,p,u,v\) 满足 \(\gcd(a,p)=1,a^{u} \equiv 1 \pmod{p},a^{v} \equiv 1 \pmod{p}\) ,则 \(a^{\gcd(u,v)} \equiv 1 \pmod{p}\)
      • 证明
        • \(ux+vy= \gcd(u,v)\) ,取它的一组解满足 \(x>0,y \le 0\) ,则 \(a^{\gcd(u,v)} \equiv a^{\gcd(u,v)}(a^v)^{-y}=a^{\gcd(u,v)-vy}=a^{ux}=(a^u)^x \equiv 1^x \equiv 1 \pmod{p}\)

扩展欧拉定理

  • 扩展欧拉定理:对于正整数 \(a,b,p\) 均有 \(a^b \equiv \begin{cases}a^{b \bmod \varphi(p)} &\gcd(a,p)=1 \\ a^{b} &\gcd(a,p) \ne 1,b<\varphi(p) \\ a^{b \bmod \varphi(p)+\varphi(p)} &\gcd(a,p) \ne 1,b \ge \varphi(p)\end{cases} \pmod{p}\)
  • 证明
    • \(\gcd(a,p)=1\) 时,设 \(b=q \times \varphi(p)+r\) ,其中 \(0 \le r< \varphi(p)\) ,即 \(r=b \bmod \varphi(p)\) 。则有 \(a^b = a^{q \times \varphi(p)+r}=(a^{\varphi(p)})^q \times a^r \equiv 1^q \times a^r \equiv a^r= a^{b \bmod \varphi(p)} \pmod{p}\)
    • \(\gcd(a,p) \ne 1\) 时的证明极其复杂,请参考 link 或者 OI WiKi 中的证明。
  • 例题

乘法逆元

  • 乘法逆元:若关于整数 \(a,b\) 的线性同余方程 \(ax \equiv 1 \pmod{b}\) 存在解,则将 \(x\) 称作 \(a\)\(b\) 的乘法逆元(简称逆元),记作 \(a^{-1} \pmod{b}\) ,在不会引起误解时常常简记为 \(a^{-1}\)
    • 貌似数奥中把这个叫做数论倒数。
    • \(b|a\) 时不存在 \(a\) 的逆元 \(a^{-1} \pmod{b}\)
    • 特别地,有 \(1^{-1} \equiv 1 \pmod{b}\)
      • 证明:对于 \(\forall b \in \mathbf{Z}\) ,有 \(1 \times 1 \equiv 1 \pmod{b}\) ,故 \(1\)\(b\) 的逆元为 \(1\)
  • 性质
    • \(n\) 为正整数,则 \(2^{-1} \equiv n+1 \pmod{2n+1}\)
      • 证明:已知 \(2x \equiv 1 \pmod{2n+1}\) ,设 \(2x=(2n+1)k+1\) ,又因为 \(2x\) 为偶数, \(k\) 的最小正整数解为 \(1\) ,代入得 \(x=n+1\)
    • \(b\) 为质数,且 \(a<b\) ,则 \(a^{-1} \equiv a^{b-2} \pmod{b}\)
      • 证明:依据费马小定理,有 \(a^{b-1} \equiv 1 \pmod{b}\) ,即 \(a \times a^{b-2} \equiv 1 \pmod{b}\) ,则 \(a\)\(b\) 的乘法逆元为 \(a^{b-2}\)
    • \(\gcd(a,b)=1\) ,有 \((a^{-1})^{-1} \equiv a \pmod{b}\)
  • 如何求逆元(边算边取模)
    • 扩展欧几里得
      • 限制条件: \(\gcd(a,b)=1\)

      • \(ax=bk+1,y=-k\) ,原方程可改写为 \(ax+by=1\) ,用 \(exgcd\) 解得一组特解 \(x_0,y_0\)\(x\) 的最小正整数解为 \((x+b)\bmod b\)

      • 时间复杂度为 \(O(\log \max(a,b))\)

      • luogu P1082 [NOIP2012 提高组] 同余方程

        点击查看代码
        ll exgcd(ll a,ll b,ll &x,ll &y)
        {
        	if(b==0)
        	{
        		x=1;
        		y=0;
        		return a;
        	}
        	else
        	{
        		ll d=exgcd(b,a%b,y,x);
        		y-=a/b*x;
        		return d;
        	}
        }
        int main()
        {
        	ll a,b,x=0,y=0;
        	cin>>a>>b;
        	exgcd(a,b,x,y);
        	x=(x%b+b)%b;
        	cout<<x<<endl;
        }
        
      • luogu P2613 【模板】有理数取余

        点击查看代码
        const ll p=19260817;
        ll exgcd(ll a,ll b,ll &x,ll &y)
        {
        	if(b==0)
        	{
        		x=1;
        		y=0;
        		return a;
        	}
        	else
        	{
        		ll d=exgcd(b,a%b,y,x);
        		y-=a/b*x;
        		return d;
        	}
        }
        int main()
        {
        	ll a,c,d,x=0,y=0;
        	c=read();
        	a=read();
        	d=exgcd(a,p,x,y);
        	if(c%d==0)
        	{
        		x=(x*c/d)%p;
        		x=(x%p+p)%p;
        		cout<<x<<endl;
        	}
        	else
        	{
        		cout<<"Angry!"<<endl;
        	}
        	return 0;
        }
        
    • 快速幂+费马小定理
      • 限制条件: \(b\) 为质数。

      • 因为 \(b\) 为质数, \(ax \equiv 1 \pmod{b}\) ,依据费马小定理,则 \(ax \equiv 1 \equiv a^{b-1} \pmod{b}\) ,故 \(x \equiv a^{b-2} \pmod{b}\) 。用快速幂求出 \(a^{b-2} \bmod b\) ,即为所求。

      • 时间复杂度为 \(O(\log b)\)

      • luogu P1082 [NOIP2012 提高组] 同余方程

        点击查看代码
        ll qpow(ll a,ll b,ll p)
        {
        	ll ans=1;
        	a%=p;
        	while(b>0)
        	{
        		if(b&1)
        		{
        			ans=ans*a%p;
        		}
        		b>>=1;
        		a=a*a%p;
        	}
        	return ans%p;
        }
        int main()
        {
        	ll a,b;
        	cin>>a>>b;
        	cout<<qpow(a,b-2,b)<<endl;
        }
        
    • 快速幂+欧拉定理
      • 限制条件: \(\gcd(a,b)=1\)

      • 因为 \(\gcd(a,b)=1,ax \equiv 1 \pmod{b}\) ,依据欧拉定理,则 \(ax \equiv 1 \equiv a^{\varphi(b)} \pmod{b}\) ,故 \(x \equiv a^{\varphi(b)-1} \pmod{b}\) 。用快速幂求出 \(a^{\varphi(b)-1} \bmod b\) ,即为所求。

      • 如果不预处理欧拉函数,时间复杂度为 \(O(\sqrt{b} \times \log \varphi(b))\)

      • luogu P1082 [NOIP2012 提高组] 同余方程

        点击查看代码
        ll phi(ll n)
        {
            ll ans=n,i;
            for(i=2;i<=sqrt(n);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;
        }
        ll qpow(ll a,ll b,ll p)
        {
            ll ans=1;
            a%=p;
            while(b>0)
            {
                if(b&1)
                {
                    ans=ans*a%p;
                }
                b>>=1;
                a=a*a%p;
            }
            return ans%p;
        }
        int main()
        {
            ll a,b;
            cin>>a>>b;
            cout<<qpow(a,phi(b)-1,b)<<endl;
        }
        
    • 线性求 \(1 \sim n\) 或单个数的逆元(递推/递归)
      • 限制条件: \(b\) 为质数。

      • \(k=\left\lfloor\dfrac{b}{i}\right\rfloor,r=b \bmod i\) ,此时有 \(b=k \times i+r\equiv 0 \pmod{b}\) 。两边同时乘以 \(i^{-1} \times r^{-1}\)\(k \times r^{-1}+i^{-1}\equiv 0 \pmod{b}\) ,移项得 \(i^{-1}\equiv -k \times r^{-1} \pmod{b}\) ,将 \(k=\left\lfloor\dfrac{b}{i}\right\rfloor,r=b \bmod i\) 代入得 \(i^{-1}\equiv -\left\lfloor\dfrac{b}{i}\right\rfloor \times (b \bmod i)^{-1} \pmod{b}\) ,考虑消除负数取模对答案的影响,故推出逆元:\(\\i^{-1} \equiv \begin{cases}1,&i=1\\(b-\left\lfloor\dfrac{b}{i}\right\rfloor) \times (b \bmod i)^{-1}&i \ne 1\end{cases} \pmod{b}\)

      • 递推求 \(n\) 个数的逆元, \(O(n)\) 预处理, \(O(1)\) 查询。

      • 递归+记忆化求 \(n\) 个数的逆元, \(O(n)\) 预处理, \(O(1)\) 查询。

        • 递归求任意一个正整数 \(n\) 的逆元,时间复杂度为 \(O(n^{\frac{1}{3}})\)
      • luogu P3811 【模板】模意义下的乘法逆元

        点击查看代码
        ll inv[3000001];
        int main()
        {
        	ll n,p,i;
        	cin>>n>>p;
        	inv[1]=1;
        	cout<<"1"<<endl;
        	for(i=2;i<=n;i++)
        	{
        		inv[i]=(p-p/i)*inv[p%i]%p;
        		cout<<inv[i]<<endl;
        	}
        	return 0;
        }
        
    • 线性求任意 \(n\) 个数的逆元(离线)
      • 限制条件: \(b\) 为质数。
      • 对于 \(1 \le i \le n\) ,令 \(mul[i]=\prod\limits_{k=1}^{i} a_k\) 。利用 \(exgcd\) 或快速幂计算 \(invc[n]=mul[n]^{-1}\) 。对于 \(1 \le i \le n-1\) ,此时有 \(invc[i]=invc[i+1] \times a_{i+1}=mul[i]^{-1}\) 。对于 \(1 \le i \le n\) ,有 \(a_i^{-1}=mul[i-1] \times invc[i]\)
      • 时间复杂度为 \(O(n+\log b)\)
      • 例题
        • luogu P3811 【模板】模意义下的乘法逆元

          点击查看代码
          ll mul[3000001],invc[3000001],inv[3000001],w[3000001];//防止重名,此处的w[]即为上文的a[]
          ll qpow(ll a,ll b,ll p)
          {
              ll ans=1;
              while(b>0)
              {
                  if(b&1)
                  {
                      ans=ans*a%p;
                  }
                  b>>=1;
                  a=a*a%p;
              }
              return ans%p;
          }
          int main()
          {
              ll n,p,i;
              cin>>n>>p;
              mul[0]=1;
              for(i=1;i<=n;i++)
              {
                  w[i]=i;
                  mul[i]=((mul[i-1]%p)*(w[i]%p))%p;
              }
              invc[n]=qpow(mul[n],p-2,p);
              for(i=n-1;i>=1;i--)
              {
                  invc[i]=((invc[i+1]%p)*((w[i+1])%p))%p;
              }
              for(i=1;i<=n;i++)
              {
                  inv[i]=((invc[i]%p)*(mul[i-1]%p))%p;
                  cout<<inv[i]<<endl;
              }
              return 0;
          }
          
        • luogu P5431 【模板】模意义下的乘法逆元 2

        • LibreOJ 161. 乘法逆元 2

  • 例题

威尔逊定理

  • 威尔逊定理:若 \(p\) 为质数,则有 \((p-1)! \equiv -1 \pmod{p}\)
  • 证明
    • \(p=2\) 时,因为规定 \(0! =1\) ,所以原结论成立。
    • \(p \ne 2\) 时,根据逆元定义,对于 \(i,j \in[2,p-2]\) ,且 \(i \ne j\) ,均有 \(i^{-1} \pmod{p},j^{-1} \pmod{p} \in[2,p-2],i^{-1} \pmod{p} \ne j^{-1} \pmod{p}\) ,所以逆元是一一对应的,故 \((p-1)! \equiv 1^{\frac{p-3}{2}} \times 1 \times (p-1) \equiv-1 \pmod{p}\)
  • 例题
    • luogu T340175 Fermat-1
      • \(n!+1\) 的次小约数等价于 \(n!+1\) 的最小质因子。故若 \(d\) 不为质数,则无解;若 \(d\) 为质数,依据威尔逊定理,易知 \(d-1\) 即为满足题意的一组解。

中国剩余定理(孙子定理)

  • 中国剩余定理(孙子定理):给定 \(n\) 个两两互质的整数 \(m_1,m_2, \dots,m_n\) ,设 \(mul=\prod\limits_{i=1}^{n}m_i,r_i=\dfrac{mul}{m_i}\) ,则对于任意的 \(n\) 个整数 \(a_1,a_2, \dots,a_n\) ,方程组 \(\begin{cases}x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \dots \\ x \equiv a_n \pmod{m_n} \end{cases}\) 在模 \(mul\) 意义下的唯一解为 \(x=\sum\limits_{i=1}^{n}a_ic_i(c_i^{-1} \pmod{mul})\) ,通解可以表示为 \(x+k \times mul(k \in \mathbb{Z})\)

  • 证明

    • 原方程组在模 \(mul\) 意义下的存在解。
      • 因为 \(r_i=\dfrac{mul}{m[i]}\) 是除 \(m_i\) 所有模数的倍数,所以对于任意整数 \(j(1 \le j \le n)\) 均有 \(a_jc_j(c_j^{-1} \pmod{mul}) \equiv \begin{cases} a_i & i=j \\ 0 & i \ne j\end{cases} \pmod{m_i}\) ,所以代入 \(x=\sum\limits_{i=1}^{n}a_ir_i(r_i^{-1} \pmod{mul})\) ,原方程组成立。
    • 原方程组在模 \(mul\) 意义下的存在唯一解。
      • 假设原方程组在模 \(mul\) 意义下的存在第二个解 \(x'\) ,则一定存在一个 \(i\) 满足 \(x \not\equiv x' \pmod{m_i}\) ,故假设不成立,原结论成立。
  • 代码实现

    点击查看代码
    ll crt(ll n)
    {
    	ll mul=1,ans=0,x,y,r,i;
    	for(i=1;i<=n;i++)
    	{
    		mul*=m[i];
    	}
    	for(i=1;i<=n;i++)
    	{
    		r=mul/m[i];
    		x=y=0;
    		exgcd(r,m[i],x,y);//m_i两两互质并不代表m_i为质数
    		ans=(ans+(a[i]*r%mul)*(x+m[i])%mul)%mul;//因为exgcd求出的x可能为负数,故需要+m[i]
    	}
    	return ans;
    }
    
  • 例题

扩展中国剩余定理

  • 扩展中国剩余定理所解决的问题和中国剩余定理所解决的问题相同,但不保证 \(m_i\) 两两互质。

  • 算法流程

    • 对于第 \(1\) 个方程,有 \(x=a_1\) 是第 \(1\) 个方程的一个解。
    • 设已经求出了前 \(i-1\) 个方程所构成的方程组的一个解 \(x\) ,且有 \(mul= \operatorname{lcm}(m_1,m_2, \dots,m_{i-1}),l=x \bmod mul\) ,则 \(x+k \times mul(k \in \mathbb{Z})\) 是前 \(i-1\) 个方程所构成的方程组的通解,即 \(x \equiv l \pmod{mul}\)
    • 对于第 \(i\) 个方程,其与前 \(i-1\) 个方程组成了一个方程组 \(\begin{cases}x \equiv l \pmod{mul} \\ x \equiv a_i \pmod{m_i} \end{cases}\) ,即 \(k \times mul+y \times m_i=a_i-l\) ,此方程有解当且仅当 \(\gcd(mul,m_i)|(a_i-l)\) 。若有解,则 \(x'=x+k \times mul\) 是前 \(i\) 个方程所构成的方程组的一个解。
  • 代码实现

    点击查看代码
    ll excrt(ll n)
    {
    	ll mul=m[1],ans=a[1],x,y,c,d,i;
    	for(i=2;i<=n;i++)
    	{
    		x=y=0;
    		c=(a[i]-ans%m[i]+m[i])%m[i];//减法取模注意先加模数再取模
    		d=exgcd(mul,m[i],x,y);
    		if(c%d==0)
    		{
    			ans+=(((x+m[i])%m[i])*(c/d)%m[i])*mul;//exgcd解出来的x可能是负数
    			mul=lcm(mul,m[i]);
    			ans=(ans%mul+mul)%mul;
    		}
    		else
    		{
    			return -1;
    		}
    	}
    	return (ans+mul)%mul;
    }
    
  • 例题

    • luogu P4777 【模板】扩展中国剩余定理(EXCRT)
    • LibreOJ 10213. 「一本通 6.4 例 5」Strange Way to Express Integers
    • CF787A The Monster
      • 注意解的下限是有限制的。
    • luogu P4774 [NOI2018] 屠龙勇士
      • \(s_i\) 表示攻击第 \(i\) 头巨龙时所用剑的攻击力,则转换为求方程组 \(\begin{cases}s_1x \equiv a_1 \pmod{m_1} \\ s_2x \equiv a_2 \pmod{m_2} \\ \dots \\ s_nx \equiv a_n \pmod{m_n} \end{cases}\) 不小于 \(\max\limits_{i=1}^{n} \{ \left\lceil\dfrac{a_i}{s_i}\right\rceil \}\) 的最小非负整数解。接下来和扩展剩余定理推导内容除 \(mul\) 的取值外基本一致。

      • 设已经求出了前 \(i-1\) 个方程所构成的方程组的一个解 \(x\) ,且有 \(mul= \operatorname{lcm}(\dfrac{m_1}{\gcd(m_1,s_1)},\dfrac{m_2}{\gcd(m_2,s_2)}, \dots,\dfrac{m_{i-1}}{\gcd(m_{i-1},s_{i-1})}),l=x \bmod mul\) ,则 \(x+k \times mul(k \in \mathbb{Z})\) 是前 \(i-1\) 个方程所构成的方程组的通解,即 \(x \equiv l \pmod{mul}\)

        • \(i\) 个方程实际上是 \(x \equiv x'' \pmod{\dfrac{m_i}{\gcd(m_i,s_i)}}\) ,其中 \(x''\)\(s_ix''+m_iy=a_i\) 的一组特解。故在合并同余方程时,模数已经发生由原来的 \(m_i\) 变成了 \(\dfrac{m_i}{\gcd(m_i,s_i)}\)
      • 对于第 \(i\) 个方程,其与前 \(i-1\) 个方程组成了一个方程组 \(\begin{cases}x \equiv l \pmod{mul} \\ s_ix \equiv a_i \pmod{m_i} \end{cases}\) ,即 \(k \times mul \times s_i+y \times m_i=a_i-l \times s_i\) ,此方程有解当且仅当 \(\gcd(mul \times s_i,m_i)|(a_i-l \times s_i)\) 。若有解,则 \(x'=x+k \times mul\) 是前 \(i\) 个方程所构成的方程组的一个解。

        点击查看代码
        ll excrt(ll n)
        {
        	ll mul=1,ans=0,x,y,c,d,i,maxx=0;
        	for(i=1;i<=n;i++)
        	{
        		x=y=0;
        		it=s.upper_bound(a[i]);//注意是不大于
        		if(it!=s.begin())
        		{
        			it--;
        		}
        		maxx=max(maxx,(ll)ceil(1.0*a[i]/(*it)));
        		c=(a[i]-((*it)%m[i])*(ans%m[i])%m[i]+m[i])%m[i];
        		d=exgcd((*it)*mul,m[i],x,y);
        		if(c%d==0)
        		{
        			ans+=(((x+m[i])%m[i])*(c/d)%m[i])*mul;
        			mul=lcm(mul,m[i]/gcd(m[i],(*it)));	
        			ans=(ans%mul+mul)%mul;
        		}
        		else
        		{
        			return -1;
        		}
        		s.erase(it);
        		s.insert(atk[i]);
        	}
        	return ans+(ll)ceil(1.0*(maxx-ans)/mul)*mul;
        }
        

高次同余方程

  • 形如 \(a^{x} \equiv b \pmod{p}\) ,其中已知 \(a,b,p\) ,求非负整数解 \(x\)
    • \(\gcd(a,p)=1\) ,但不保证 \(p \in \mathbb{P}\) 时,使用 Baby Step,Giant Step /大步小步算法求解。
      • 由欧拉定理,有 \(a^{\varphi(p)} \equiv 1 \pmod{p}\) ,即循环节为 \(\varphi(p)-1\) ,故只找到最小的一个 \(x \in [0,\varphi(p)-1]\) 即可得到所有满足条件的 \(x\)

      • 算法流程

        • \(x=i \times \left\lceil \sqrt{p} \right\rceil-j\) ,其中 \(j \in [0,\left\lceil \sqrt{p} \right\rceil)\) ,则方程改写为 \(a^{i \times \left\lceil \sqrt{p} \right\rceil-j} \equiv b \pmod{p}\)
        • 又因为 \(a,p\) 互质,移项得到 \((a^{\left\lceil \sqrt{p} \right\rceil})^{i} \equiv a^{j}b \pmod{p}\)
          • 同时也解释了为什么要求 \(a,p\) 互质。
        • 对于每个 \(j \in [0,\left\lceil \sqrt{p} \right\rceil)\) ,将 \(a^{j}b \bmod{p}\) 插入到一个哈希表中,接着枚举 \(i \in [0,\left\lceil \sqrt{p} \right\rceil]\) ,计算出 \((a^{\left\lceil \sqrt{p} \right\rceil})^{i} \bmod{p}\) 后在哈希表中查找即可。
      • 代码实现

        点击查看代码
        ll qpow(ll a,ll b,ll p)
        {
        	ll ans=1;
        	while(b>0)
        	{
        		if(b&1)
        		{
        			ans=ans*a%p;
        		}
        		b>>=1;
        		a=a*a%p;
        	}
        	return ans;	
        }
        ll bsgs(ll a,ll b,ll p)
        {
        	if(1%p==b%p)
        	{
        		return 0;
        	}
        	else
        	{
        		map<ll,ll>vis;
        		ll k=sqrt(p)+1,i,sum;
        		for(i=0;i<=k-1;i++)
        		{
        			vis[b*qpow(a,i,p)%p]=i;
        		}
        		a=qpow(a,k,p);
        		for(i=0;i<=k;i++)
        		{
        			sum=qpow(a,i,p);
        			if(vis.find(sum)!=vis.end())
        			{
        				if(i*k-vis[sum]>=0)
        				{
        					return i*k-vis[sum];
        				}
        			}
        		}
        		return -1;
        	}
        }
        
      • 例题

    • 当不保证 \(\gcd(a,p)=1\) ,但 \(p \in \mathbb{P}\) 时,可以转化为 Baby Step,Giant Step 求解。
      • 由于不保证 \(\gcd(a,p)=1\) ,故当 \(a \equiv b \equiv 0 \pmod{p}\)\(\gcd(a,p)=1\) 时,同余方程存在非负整数解,其中前者的最小非负整数解为 \(x=1\) ,后者则可以通过 Baby Step,Giant Step 求解;否则不存在解。
      • 例题
    • 当不保证 \(\gcd(a,p)=1\) 和不保证 \(p \in \mathbb{P}\) 时,使用扩展 Baby Step,Giant Step 算法求解。
      • \(d_{1}=\gcd(a,p)\) ,若 \(d_{1} \nmid b\) 则无解,否则同余两边同时除以 \(d_{1}\) ,得到 \(\frac{a}{d_{1}}a^{x-1} \equiv \frac{b}{d_{1}} \pmod{\frac{p}{d_{1}}}\)

      • \(a,\frac{p}{d_{1}}\) 仍不互质则继续取 \(d_{2}=\gcd(a,\frac{p}{d_{1}})\) ,同余两边同时除以 \(d_{2}\) 得到 \(\frac{a^{2}}{d_{1}d_{2}}a^{x} \equiv \frac{b}{d_{1}d_{2}} \pmod{\frac{p}{d_{1}d_{2}}}\)

      • 重复这个过程直至 \(\gcd(a,\frac{p}{\prod\limits_{i=1}^{k}d_{i}})=1\) ,此时有 \(\frac{a^{k}}{\prod\limits_{i=1}^{k}d_{i}}a^{x-k} \equiv \frac{b}{\prod\limits_{i=1}^{k}d_{i}} \pmod{\frac{p}{\prod\limits_{i=1}^{k}d_{i}}}\)

      • 因为 \(\gcd(a,\frac{p}{\prod\limits_{i=1}^{k}d_{i}})=1\) ,所以 \(\gcd(\frac{a^{k}}{\prod\limits_{i=1}^{k}d_{i}},\frac{p}{\prod\limits_{i=1}^{k}d_{i}})=1\) ,乘过去后求逆元就和正常的 Baby Step,Giant Step 算法一样了。

      • 对于 \(x<k\) 的情况,在求 \(k\) 的过程中判断即可。

      • 代码实现

        点击查看代码
        ll qpow(ll a,ll b,ll p)
        {
        	ll ans=1;
        	while(b)
        	{
        		if(b&1)
        		{
        			ans=ans*a%p;
        		}
        		b>>=1;
        		a=a*a%p;
        	}
        	return ans;
        }
        ll exgcd(ll a,ll b,ll &x,ll &y)
        {
        	if(b==0)
        	{
        		x=1;
        		y=0;
        		return a;
        	}
        	else
        	{
        		ll d=exgcd(b,a%b,y,x);
        		y-=a/b*x;
        		return d;
        	}
        }
        ll inv(ll a,ll p)
        {
        	ll x,y;
        	exgcd(a,p,x,y);
        	return (x%p+p)%p;
        }
        ll bsgs(ll a,ll b,ll p)
        {
        	if(1%p==b%p)
        	{
        		return 0;
        	}
        	else
        	{
        		unordered_map<ll,ll>vis;
        		ll k=sqrt(p)+1,i,sum=1;
        		for(i=0;i<=k-1;i++)
        		{
        			b=(i==0)?b:b*a%p;
        			vis[b]=i;
        		}
        		a=qpow(a,k,p);
        		for(i=0;i<=k;i++)
        		{
        			sum=(i==0)?sum:sum*a%p;
        			if(vis.find(sum)!=vis.end())
        			{
        				if(i*k-vis[sum]>=0)
        				{
        					return i*k-vis[sum];
        				}
        			}
        		}
        		return -1;
        	}
        }
        ll exbsgs(ll a,ll b,ll p)
        {
        	b%=p;//防止后面判 b%d==0 时出错
        	if(b==1||p==1)//特判 0 的情况
        	{
        		return 0;
        	}
        	else
        	{
        		ll x,y,d=exgcd(a,p,x,y),k=0,mul=1;
        		while(d!=1)
        		{
        			if(b%d==0)
        			{
        				k++;
        				b/=d;
        				p/=d;
        				mul=(a/d)*mul%p;
        				if(mul==b)//已经是答案
        				{
        					return k;
        				}
        				else
        				{
        					d=exgcd(a,p,x,y);
        				}
        			}
        			else
        			{
        				return -1;
        			}
        		}
        		ll ans=bsgs(a,b*inv(mul,p)%p,p);
        		return (ans!=-1)*k+ans;
        	}
        }
        
      • 例题

  • 形如 \(x^{a} \equiv b \pmod{p}\) ,其中已知 \(a,b,p\) ,求非负整数解 \(x\)
posted @ 2023-12-18 11:57  hzoi_Shadow  阅读(112)  评论(0编辑  收藏  举报
扩大
缩小