『数论』

數論,一生之敵!

前言

今天 LJ 讲了一堆数论知识,于是自己整理了一下。

正文

扩展 gcd / exgcd

exgcd 其实是解决这样一个不定方程 \(ax+by=c\) 的,当然这个不定方程等价于 \(ax \equiv c \pmod p\) 。(很显然)

看到这里,你想到了什么?对,我们小学二年级就学过的 Bezout 定理(译作裴蜀定理或贝祖定理)。

Bezout 定理:若 \(a,b \in Z\), 则一定存在一对整数 \(x,y\) 满足

\[ax+by=\gcd(a,b) \]

证明

不妨将上式记为 \((1)\) ,记 \(d=\gcd(a,b)\)

\(a,b\) 中有一数为 \(0\),假设 \(a=0\), 则 \(d=b\) 。此时 \((1)\) 可化为 \(by=m\) 。它有整数解,当且仅当 \(m\)\(b\) 的倍数。

\(\because\) \(x\) 可以是任意整数

\(\therefore\) 定理成立。

\(a,b\) 都不为 \(0\)

\(S\)\(a+b\) 的最小正值(最小数定理)。

由带余除法: \(a=q\times S+r\)

\(\therefore\) \(r=a-q\times S=a-q(ax+by)=a(1-q\times x)-b(q\times y)\)

\(\because\) \(q,x,y \in Z\) \(\therefore\) \(r\) 也是 \((a,b)\) 的线性组合。

\(\because\) \(S\)\(ax+by\) 的最小值 \(\therefore\) \(r=0\) \(\therefore\) \(S|a\)

同理可得: \(S|b\)

\(\therefore\) \(S|d\)

\(\because\) \(d|a,d|b\) \(\therefore\) \(d|(ax+by)\)

\(\therefore\) \(d|S\)

\(\therefore\) \(S=d\) \(\blacksquare\)

当然也可以用欧几里得算法去证。

由 Bezout 定理我们知道 \(ax+by=c\)\(\gcd(a,b)|c\)

然后,很显然 \(\gcd(a,b)=\gcd(b,a \bmod b)\)

因而,我们可以得出 exgcd 的模板(求关于 \(x\) 的方程 \(ax \equiv 1 \pmod b\) 的最小正整数解):

#include<bits/stdc++.h>
#define FOR(i,j,k)  for(int i=(j);i<=(k);i++)
using namespace std;
long long a,b,x,y;
inline long long read()
{
	long long x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
void exgcd(long long a,long long b)
{
	if(!b)
	{
		x=1,y=0;
		return ;
	}
	exgcd(b,a%b);
	long long tx=x;
	x=y,y=tx-a/b*y;
}
int main()
{
	a=read(),b=read();
	exgcd(a,b);
	x=(x%b+b)%b;
	printf("%lld\n",x);
	return 0;
}

(这段可能有点奇怪,因为是差不多半年前写的)


乘法逆元

定义:如果 \(ax \equiv 1 \pmod p\), 则称 \(a\) 关于 \(p\) 的乘法逆元为 \(x\)

一般编程时用 inv 表示。

然后我们一看,这不就是上文的 ecgcd 吗?

乘法逆元多用于 除法取模

\(x\)\(b\) 关于 \(p\) 的乘法逆元,则有 \(a/b \equiv ax \pmod p\)

有些题需要用到 \(1 \sim n\) 关于 \(p\) 的乘法逆元,我们发现,此时用 exgcd 时间复杂度不理想,于是诞生了一种时间复杂度为 \(O(n)\)递推算法

\(p=k \times i+r\)\((r < i,1<i<p)\) , 则有

\[k \times i +r \equiv 0 \pmod p \]

两边同乘 \(i^{-1}+r^{-1}\)

\[k \times r^{-1}+i^{-1} \equiv 0 \pmod p \]

移项得

\[i^{-1} \equiv - \lfloor \dfrac{p}{i}\rfloor \times (p \bmod i)^{-1 } \pmod p \]

于是我们就可以递推了,注意边界为 \(i^{-1}\equiv 1 \pmod p\)

inv[i]=(mod-mod/i)*inv[mod%i]%mod;

题目:P3811 【模板】乘法逆元


欧拉函数 \(\varphi\)

定义:欧拉函数 \(\varphi(x)\) 表示不超过 \(x\) 且与 \(x\) 互质的正整数个数,欧拉函数为 积性函数 即当 \(n,m\) 互质时 \(\varphi(nm)=\varphi(n)\cdot \varphi(m)\)

积性函数的证明:见 command_block 神仙的 blog

表示:将 \(x\) 分解成 \(p_{1}^{k_1}\times p_{2}^{k_2} \times \cdots \times p_n^{k_n}\) ,则有

\[\varphi(x)=x \prod_{i=1}^{n} (1-\dfrac{1}{p_i}) \]

证明

\(x=p\), \(p\) 表示质数,则 \(\varphi(x)=x-1\) ,这是显然的。

\(x=p^k\),则 \(x\) 以内的正整数只要没有 \(p\) 这个质因数就与 \(x\) 互质。那么,正难则反,与 \(x\) 不互质的数有 \(p,2 \cdot p,3\cdot p, \cdots ,p^{k-1}p\),共 \(p^{k-1}\) 个数,所以 \(\varphi(x)=p^k-p^{k-1}=p^{k}(1-\dfrac{1}{p})\)

\(x\) 为合数,则 \(x\) 可以分解为 \(p_{1}^{k_1}\times p_{2}^{k_2} \times \cdots \times p_n^{k_n}\)。由于欧拉函数是积性函数,所以

\[\varphi(x)=\prod\limits_{i=1}^{n} \varphi(p_i^{k_i})=\prod\limits_{i=1}^{n} p_i^{k_i}(1-\dfrac{1}{p_i})=x\prod\limits_{i=1}^{n} (1-\dfrac{1}{p_i}) \]

\(\blacksquare\)

那么代码也就呼之欲出了

int phi(int x)
{
	int ans=x;
	for(int i=2;i<=sqrt(x);i++)
		if(x%i==0)
		{
			ans-=ans/i;
			while(x%i==0)	x/=i;
		}
	if(x>1)	ans-=ans/x;
	return ans;
}

\(\uparrow\) 求单个数的 \(\varphi\)

\(\downarrow\)\(1\sim n\)\(\varphi\)

前置知识:若 \(p |n\)\(n\) 含有 \(nq\) 所有的质因子,所以 \(\varphi(np)=p\times n\prod \limits _{i=1}^{k} (1-\dfrac{1}{p_i})=p \times \varphi(n)\)

\(p\not| n\)\(\varphi(np)=\varphi(p) \times \varphi(n)=(p-1)\times \varphi(n)\) .

bitset<2333> used;
int p[233],cnt;
long long phi[2333];
inline void getphi()
{
	phi[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!used[i])
			p[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*p[j]<=n;j++)
		{
			int val=i*p[j];
			used[val]=1;
			phi[val]=phi[i]*(i%p[j]?p[j]-1:p[j]);
			if(i%p[j]==0)	break;
		}
	}
}

今天模拟赛做到一道需要欧拉函数的例题 CF870F Paths

可以用欧拉函数做的一些事情(更新中)

给定一个数 \(n\),求 \(1\sim n\) 中与 \(n\) 互质的数的和。

先证一个引理:若 \(\gcd(n,i)=1\)\(\gcd(n,n-i)=1\)

考虑反证。令 \(k=\gcd(n,n-i)\),且 \(k\not = 1\)。则 \(k \mid n,k \mid n-i\)\(k \mid i\),那么 \(\gcd(i,n)=k\) 矛盾。

此时问题就变得十分简单,答案就是 \(\dfrac{n \times \varphi(n)}{2}\)。因为 \(i\)\(n-i\) 总是成对出现。


欧拉定理

内容

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

证明

\(p_1,p_2,\cdots,p_{\varphi(m)}\)\(1\)\(m\) 中,与 \(m\) 互质的数。

\(x_i=a\times p_i\),易发现 \(x_i\)\(m\) 两两不同。

证明:我们考虑反证,若 \(x_i \equiv x_j \pmod m\),则 \(x_i-x_j \equiv 0 \pmod m\),即 \(a(p_i-p_j) \equiv 0 \pmod m\)。由于 \(\gcd(a,m)=1\)\(p_i,p_j \le m\)\(p_i-p_j\) 一定小于 \(m\),所以矛盾。

同时每一个 \(x_i\)\(m\) 的结果均与 \(m\) 互质。

证明:依然是反证,若 \(x_i=km+r\) \((0\le r<m)\)\(\gcd(r,m)\not = 1\)\(x_i-km=r\),故而 \(x_i \equiv r \pmod m\),即 \(ap_i \equiv r \pmod m\)\(a,p_i\) 均与 \(m\) 互质, \(r\) 亦与 \(m\) 互质,矛盾。

由上面的两个性质可以得出, \(x_1,x_2,\cdots,x_{\varphi(m)}\)\(m\) 的结果是 \(\varphi(m)\) 个不同的与 \(m\) 互质的数,那不就是 \(p_1,p_2,\cdots,p_{\varphi(m)}\) 这个集合。
所以有

\[\prod_{i=1}^{\varphi(m)} x_i \equiv \prod_{i=1}^{\varphi(m)} p_i \pmod m \]

\[\prod_{i=1}^{\varphi(m)} ap_i \equiv \prod_{i=1}^{\varphi(m)} p_i \pmod m \]

所以

\[a^{\varphi(m)}\equiv 1 \pmod m \]

\(\blacksquare\)


费马小定理

内容\(a^{p-1}\equiv 1 \pmod p\),其中 \(\gcd(a,p)=1\)\(p\) 为质数。

证明:欧拉定理的一个特例。

用途: 可以求上文的乘法逆元


扩展欧拉定理

内容

\[a^c \equiv\begin{cases} a^{c \bmod \varphi(m)},\qquad \gcd(a,m)=1\\ a^c, \qquad \gcd(a,m)\not =1,c\le \varphi(m)\\ a^{ \left(c \bmod \varphi(m) \right)+ \varphi(m)} \qquad \gcd(a,m)\not = 1, c\ge \varphi(m) \end{cases} \pmod m\]

证明

分开来证。

情况 1 の 证明

不妨设 \(c=k\varphi(m)+r\),其中 \(0\le r<m\)
\(a^c=a^{\varphi(m)^k}\times a^r=a^{\varphi(m)^k}\times a^{c \bmod \varphi(m)}\)

由欧拉定理可知 \(a^{\varphi(m)}\equiv1 \pmod m\)

所以 \(a^c \equiv a^{c \bmod \varphi(m)}\)

情况 2 の 证明:显然。

情况 3 の 证明

类似于欧拉函数部分的证明。

我们不妨从 \(a\) 的质因子 \(p\) 入手。

即证明 \(p^{ \left(c \bmod \varphi(m) \right)+ \varphi(m)}\equiv p^c \pmod m,c\ge \varphi(m)\)

Case 1

\(\gcd(m,p)=1\),则为情况 1, \(p^c \equiv p^{c \bmod \varphi(m)} \pmod m\), 又因 \(p^{\varphi(m)}\equiv 1 \pmod m\), 所以 \(p^c \equiv p^{ \left(c \bmod \varphi(m) \right)+ \varphi(m)}\pmod m\)

Case 2

\(p\)\(a,m\) 的公因子,令 \(m=s \times p^r\)\(\gcd(s,p)=1\),所以 \(\gcd(s,p^r)=1\)

因为 \(\gcd(p^x-1,p^r)=1,1\le x\le r\)\(p^x-1\) 中没有 \(p\) 这个因子, \(p^r\) 只有 \(p\) 这个质因子),所以 \(\varphi(p^r)\ge r\)

所以 \(\varphi(m)=\varphi(s) \times \varphi(p^r)\ge \varphi(p^r)\ge r\)

由欧拉定理 \(p^{\varphi(s)}\equiv 1 \pmod s\),因欧拉函数是积性函数可知 \(\varphi(m)=\varphi(s)\times \varphi(p^r)\),所以 \(p^{\varphi(m)}\equiv 1 \pmod s\)

同时乘 \(p^r\) 可得 \(p^{r+\varphi(m)}\equiv p^r \pmod m\)

所以有 \(p^k \equiv p^{k-r}\times p^r \equiv p^{k-r}\times p^{r+\varphi(m)} \equiv p^{k+\varphi(m)}\pmod m, k \ge r\)

易发现该式可以「 套娃 」, \(p^k \equiv p^{k+x\varphi(m)},x \in \mathbb{N}^+\)

\(c < 2\varphi(m)\)\(c \bmod \varphi(m) + \varphi(m)=c\),结论显然成立。

\(c\ge 2\varphi(m)\)\(c \bmod \varphi(m) + \varphi(m) \ge \varphi(m)\ge c\),故对 \(p^ {c \bmod \varphi(m)+\varphi(m)}\) 进行 「 套娃 」,易得 \(p^ {c \bmod \varphi(m)+\varphi(m)}\equiv p^c \pmod m\)

(终于搞完了,看网上很多 blog 这里都说什么 显然/即,然后我就非常崩溃,于是用比较容易理解的话语证明了这个部分,不过也许是我太菜了,只有我觉得很不显然?)

证明完 \(p^{ \left(c \bmod \varphi(m) \right)+ \varphi(m)}\equiv p^c \pmod m,c\ge \varphi(m)\)

接下来就可以得到 \({p^k}^c \equiv {p^k}^{ \left(c \bmod \varphi(m) \right)+ \varphi(m)} \pmod m\)

那么将 \(a\) 分解为 \(p_1 ^{k_1}\times p_2^{k_2}\times \cdots \times p_x ^{k_x}\)

则有 \({p_i^{k_i}}^c\equiv {p_i ^ {k_i}}^{\left(c \bmod \varphi(m) \right)+ \varphi(m)} \pmod m\)

将这些式子全部乘起来,就有 \(a^c \equiv a^{\left(c \bmod \varphi(m) \right)+ \varphi(m)} \pmod m\)

\(\blacksquare\)

例题P5091 【模板】扩展欧拉定理CF906D Power Tower(幂塔),P4139 上帝与集合的正确用法(较为简单的幂塔)


中国剩余定理/CRT

前言

三人同行七十稀,五树梅花廿一枝,七子团圆正半月,除百零五便得知

小学奥数老师告诉我说这是 中国剩余定理,后来貌似在某个电视剧(《少年派》?)里面看到有人用这个东西。

内容

\[\begin{cases} x \equiv b_1 \pmod {a_1}\\ x \equiv b_2 \pmod {a_2}\\ \qquad \cdots\\ x \equiv b_n \pmod {a_n} \end{cases}\]

其中 \(a_i\) 互质,求 \(x\) 的最小正整数解。

解法

\(A = \prod \limits_{i=1}^n a_i\)\(A_i=\dfrac{A}{a_i}\)\(t_i\)\(m_i\) 的逆元。

可以构造出一个解 \(x= \sum \limits_{i=1}^k b_iA_it_i\)

所以任意解 \(x_0=x+ k\times A\)

故最小正整数解 \(x_{\min}= x_0 \bmod A\)

证明

比较显然。

先考虑构造 \(x=\sum \limits _{i=1}^n b_iA_i \times ?\)

\(x\) 代入第 \(i\) 条式子易发现除了 \(b_iA_i \times ?\) 其他的都被 \(\bmod\) 掉了,因为 \(\forall j \in [1,n],j\not = i\),都有 \(a_i|A_j\)

那么就是要满足 \(b_iA_i\times ? \equiv b_i \pmod {a_i}\),而 \(b_iA_it_i\) 正好满足。

最小整数解 \(x_{\min}=\sum \limits_{i=1}^k b_iA_it_i \bmod A\) 又是为何?

\(a_i\) 两两互质,对于第 \(i\) 个式子可以得到任意解 \(x_0=x+ k \times a_i\)。故而最后合在一起就是 \(x_0=x+ k \times A\)

所以最小正整数解 \(x_{\min}=\sum \limits_{i=1}^k b_iA_it_i \bmod A\)

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


扩展中国剩余定理/exCRT

内容

\[\begin{cases} x \equiv b_1 \pmod {a_1}\\ x \equiv b_2 \pmod {a_2}\\ \qquad \cdots\\ x \equiv b_n \pmod {a_n} \end{cases}\]

此时 \(a_i\) 不再互质,求 \(x\) 的最小整数解。

求解

假设我们已经求出了前 \(k-1\) 个方程组成的同余方程组的解 \(x'\)

\(M=\operatorname{lcm}(a_i),i\in \{1,2,\cdots ,k-1\}\),则其通解为 \(x'+t\times M\),这是显然的。

要使得 \(x'+t\times M\) 满足第 \(k\) 条同余方程,即找出一个整数 \(p\),使得 \(x'+p\times M \equiv b_k \pmod {a_k}\)

\(p\times M \equiv b_k -x' \pmod {a_k}\),容易发现对于这个式子我们可以用 exgcd 求这个 \(p\)

若无解,则整个同余方程组无解。

若有解,则前 \(k\) 个同余方程组成的方程组的解 \(x_k=x' +p \times M\)

这样一项一项递推下去,就得到了最终答案。

注意: 求 \(\operatorname{lcm}\) 的时候要注意有可能爆 long long,需要龟速乘。

代码P4777 【模板】扩展中国剩余定理(EXCRT)

#include<bits/stdc++.h>
#define FOR(i,j,k)  for(int i=(j);i<=(k);i++)
using namespace std;
int n;
long long a[100005],b[100005];
inline long long read()
{
	long long x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
inline long long mul(long long a,long long b,long long mod)
{
	long long res=0;
	while(b)
	{
		if(b&1)	res=(res+a)%mod;
		a=(a+a)%mod;b>>=1;
	}
	return res;
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
	if(!b){x=1,y=0;return a;}
	long long gcd=exgcd(b,a%b,x,y);
	long long t=x;x=y;y=t-a/b*y;
	return gcd;
}
inline long long excrt()
{
	long long ans=b[1],M=a[1];
	long long x,y;
	for(int i=2;i<=n;i++)
	{
		long long B=(b[i]-ans%a[i]+a[i])%a[i];
		long long gcd=exgcd(M,a[i],x,y),mod=a[i]/gcd;
		if(B%gcd!=0)	return -1;
		x=mul(x,B/gcd,mod);
		ans+=x*M;
		M*=mod;
		ans=(ans+M)%M;
	}
	return (ans+M)%M;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)	a[i]=read(),b[i]=read();
	//a[i] mod number
	//b[i] left number
	printf("%lld\n",excrt()); 
	return 0;
}


原根

:若 \(\gcd(a,m)=1\),使 \(a^k \equiv 1 \pmod m\) 成立的最小的 \(k\),成为 \(n\) 关于模 \(m\) 的阶,记作 \(\delta_m(a)\) 或者 \(\operatorname{ord}_m a\)

阶的一些性质:

  • 「1」若 \(\delta_m(a)=k\),则 \(\displaystyle\delta_m(a^t)= \frac{k}{\gcd(t,k)}\),这是十分显然的。
  • 「2」令 \(k=\delta_m(a)\),则 \(a^n \equiv 1 \pmod m\) 当且仅当 \(k\mid n\)。由欧拉定理可知 \(k\mid\varphi(m)\)
  • 「3」若\(a\equiv b \pmod m, \gcd(a,m)=1\),则 \(\delta_m(a)=\delta_m(b)\)
  • 「4」若 \(\gcd(a,m)=1\),那么 \(a^x \equiv a^y \pmod m\),的充分必要条件为 \(x \equiv y \pmod {\delta_m(a)}\)

证明:令 \(x\le y\),则 \(a^{y-x}\equiv1 \equiv a^{\delta_m(a)} \pmod m\)。故而 \(\delta_m(a) \mid y-x\),所以 \(y \equiv x \pmod {\delta_m(a)}\)

  • 「5」\(a^0,a^1,\dots,a^{\delta_m(a)}\)\(m\) 的值互不相等。

证明:反证,作差,略。

  • 「6」\(ab \equiv 1 \pmod m,\gcd(a,m)=\gcd(b,m)=1\),则 $\delta_m(a)=\delta_m(b) $。

证明:令 \(\delta_m(a)=k\),则有 \((ab)^k\equiv 1 \pmod m\),而 \(a^k \equiv 1 \pmod m\) 的充要条件为 \(b^k \equiv 1\pmod m\)

  • 「7」若 \(n \mid m\),则 \(\delta_n (a)\mid \delta_m (a)\)

证明:\(\because a^{\delta_m(a)}\equiv 1 \pmod m\)\(n \mid m\) \(\therefore a^{\delta_m(a)}\equiv 1 \pmod n\)。由性质「2」可知 \(\delta_n(a)\mid \delta_m(a)\)

  • 「8」若 \(\gcd(m,n)=\gcd(a,mn)=1\),则 \(\delta_{mn}(a)=\operatorname{lcm}(\delta_m(a),\delta_n(a))\)

证明:令 \(x=\delta_{mn}(a),y=\operatorname{lcm}(\delta_m(a),\delta_n(b))\)
\(\because a^x \equiv 1\pmod {mn}\)
\(\therefore a^x \equiv 1 \pmod m,a^x \equiv 1 \pmod n\)
\(\therefore \delta_m(a)\mid x,\delta_n(a)\mid x\)
\(\therefore y\mid x\)
\(\because \delta_m(a)\mid y,\delta_n(a)|y\)
\(\therefore a^y\equiv 1\pmod m,a^y \equiv 1 \pmod n\)
\(\because \gcd(n,m)=1\)
\(\therefore a^y \equiv 1 \pmod {mn}\)
\(\therefore x \mid y\)
\(\therefore x=y\)

  • 「9」若 \(\gcd(ab,m)=\gcd(\delta_m(a),\delta_m(b))=1\),则 \(\delta_m(ab)=\delta_m(a) \times\delta_m(b)\)

证明:令 \(x=\delta_m(a),y=\delta_m(y),z=\delta_m(ab)\)
\(\because a^x \equiv 1 \pmod m\)\(b^y \equiv 1 \pmod m\)
\(\therefore (ab)^{xy}\equiv 1 \pmod m\) \(\therefore z \mid xy\)
\(\because a^x\equiv 1 \pmod m\)\((ab)^z \equiv 1 \pmod m\)
\(\therefore a^{xz}\equiv 1 \pmod m\)\((ab)^{xz}\equiv 1 \pmod m\)
\(\therefore b^{xz}\equiv 1 \pmod m\) \(\therefore y \mid xz\)
\(\because \gcd(x,y)=1\) \(\therefore y \mid z\) 同理可得 \(x|z\)
\(\therefore \operatorname{lcm}(x,y)=xy \mid z\)
\(\therefore z=xy\)

原根
\(\gcd(g,m)=1\),若 \(\delta_m(g)=\varphi(m)\),则称 \(g\)\(m\) 的一个原根。

判断是否存在原根:若 \(m\) 有原根,则 \(m\) 一定是以下形式:\(2,4,p^k,2p^k\)。这里 \(p\) 为奇素数,\(k\) 为正整数。

证明 OI-wiki 上有。不会。

原根的判定

\(\gcd(g,m)=1\),设 \(p_1,p_2,\dots,p_k\)\(\varphi(m)\) 的所有不同素因数,则 \(g\)\(m\) 的原根当且仅当对于任意 \(\forall i \in[1,k]\),都有
$ g^{\frac{\varphi(m)}{p_i}} \not\equiv 1 \pmod m $。

证明

\(q=\varphi(m)\),假设存在一个 \(t < q\) 使得 \(g^t \equiv 1 \pmod m\),且 \(\forall i \in [1,k]: g^{\frac{q}{p_i}}\not \equiv 1\)

由 Bezout 定理可知,一定存在一组 \(k,x\) 满足 \(kt=xq+\gcd(t,q)\)

由欧拉定理可知, \(g^q \equiv 1 \pmod m\)。故有:

\[1 \equiv g^{kt}\equiv g^{xq+\gcd(t,q)}\equiv g^{\gcd(t,q)} \pmod m \]

又因 \(t<q\),故 \(\gcd(t,q)\le t <q\)

故而 \(\gcd(t,q)\) 必定至少整除 \(g^{\frac{q}{p_1}},g^{\frac{q}{p_2}},\dots,g^{\frac{q}{p_k}}\) 其中的一个。

假设 \(\gcd(t,q) \mid g^{\frac{q}{p_i}}\),则有 \(g^{\frac{q}{p_i}}\equiv g^{\gcd(t,q)}\equiv 1 \pmod m\),矛盾。

假设不成立。

原根个数定理:集合 \(S=\{g^s \mid 1 \le s \le \varphi(m),\gcd(s,\varphi(m))=1\}\) 给出了 \(m\) 所有的原根。共有 \(\varphi(\varphi(m))\) 个模 \(m\) 两两不互余的原根。

大致证明:由「原根的定义」可知,\(g^s\)\(m\) 的原根当且仅当 \(\delta_m(g^s)=\varphi(m)\)。由「阶的性质 1」可知 \(\delta_m(g^s)=\dfrac{\delta_m(g)}{\gcd(s,\varphi(m))}\)。故而 \(\gcd(s,\varphi(m))=1\)

但是我有一个疑惑,为什么不会存在一个数 \(x\not = g^s\) 但是满足 \(\delta_m(x)=\varphi(m)\)。希望有神仙可以解答一下。

求所有原根:王元曾证明最小原根是不大于 \(\sqrt[4]{m}\) 级别的。故而最小原根是很小的。不妨枚举一个最小的 \(g\),然后枚举指数即可。

原根的一些性质

「1」\(\displaystyle\prod _{s=1,s\bot\varphi(m)}^{\varphi(m)} g^s \equiv 1 \pmod m\)。原因见前「可以用欧拉函数做的一些事情」。

「2」\(\displaystyle \sum _{s=1,s\bot\varphi(m)}^{\varphi(m)} g^s \equiv \mu(m-1) \pmod m\)。目前不会。

代码

模板

#include<bits/stdc++.h>
#define FOR(i,j,k)  for(int i=(j);i<=(k);i++)
using namespace std;
int tc,cnt;
int n,d;
int prime[100005],phi[1000006];
bitset<1000006> rt;
bitset<1000006> used;
vector<int> pfact;
vector<int> proot;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
inline void sieve(int n)
{
	phi[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!used[i])	prime[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&prime[j]*i<=n;j++)
		{
			used[i*prime[j]]=1;
			if(i%prime[j])	phi[i*prime[j]]=phi[i]*(prime[j]-1);
			else
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
		}
	}
	rt[2]=rt[4]=true;
	for(int i=2;i<=cnt;i++)
	{
		for(int j=1;1ll*j*prime[i]<=n;j*=prime[i])	rt[j*prime[i]]=1;
		for(int j=2;1ll*j*prime[i]<=n;j*=prime[i])	rt[j*prime[i]]=1;
	}
}
inline void divide(int x)
{
	for(int i=1;prime[i]<=x;i++)
		if(x%prime[i]==0)
			pfact.push_back(prime[i]);
}
inline int gcd(int a,int b){return (!b)?a:gcd(b,a%b);}
inline int f(int base,int y,int mod)
{
	int res=1,p=base;
	while(y)
	{
		if(y&1)	res=1ll*res*p%mod;
		p=1ll*p*p%mod;
		y>>=1;
	}
	return res;
}
int main()
{
	tc=read();
	sieve(1000000);
	while(tc--)
	{
		n=read(),d=read();
		if(rt[n])
		{
			pfact.clear();
			proot.clear();
			divide(phi[n]);
			int gmin=0;
			while(true)
			{
				gmin++;
				bool flag=true;
				if(gcd(n,gmin)!=1)	continue;
				for(int j=0;j<pfact.size();j++)
					if(f(gmin,phi[n]/pfact[j],n)==1)
					{
						flag=false;break;
					}
				if(flag)	break;
			}
			long long g=1;
			for(int i=1;i<phi[n];i++)
			{
				g=g*gmin%n;
				if(gcd(phi[n],i)==1)	proot.push_back(g);
			}
			if(!proot.size())	proot.push_back(gmin);
			sort(proot.begin(),proot.end());
			printf("%d\n",phi[phi[n]]);
			for(int i=d-1;i<phi[phi[n]]&&i<proot.size();i+=d)
				printf("%d ",proot[i]);
			puts("");
		}
		else	puts("0\n");
	}
	return 0;
}


二次剩余

以下内容均默认模数 \(p\) 为奇质数。

内容:若有 \(x\) 满足 \(x^2\equiv n \pmod p\),则称 \(n\) 在模 \(p\) 意义下是二次剩余。说人话就是模意义开根。

解的数量:对于模 \(p\) 意义下的二次剩余 \(n\) 有几个解?

假设有多组解,其中两组分别为 \(x_1,x_2\)。那么有 \({x_1}^2 \equiv{x_2}^2 \pmod p\),移项得: \((x_1-x_2)(x_1+x_2) \equiv 0 \pmod p\)

因为 \(p\) 为质数且 \(x_1 \not = x_2\),所以 \(x_1+x_2=0\),所以方程只有两个解,她们互为相反数。

那么我们还可以知道,每一对相反数都有一个二次剩余,且这些二次剩余互不相等。

故而二次剩余的数量恰为 \(\dfrac{p-1}{2}\),二次非剩余的数量与之相等。

欧拉准则:如何判断一个数是不是二次剩余?

假定 \(n \not = 0\)

由费马小定理可得 \(n^{{p-1}} \equiv 1\pmod p\)。也就是说 \(n^{\frac{p-1}{2}}\)\(1\) 开根的结果,故而 \(n^{\frac{p-1}{2}}\) 只能是 \(1\)\(-1\)

\(n\) 是二次剩余,则 \(n^{\frac{p-1}{2}}\equiv (x^2)^{\frac{p-1}{2}}\equiv x^{p-1}\equiv 1\pmod p\)

\(n^{\frac{p-1}{2}}\equiv 1 \pmod p\),由于 \(p\) 为奇质数,则 \(n\) 必然能表示成 \(g^t\) 其中 \(g\)\(p\) 的原根。那么 \(g^{t\frac{p-1}{2}}\equiv 1 \pmod p\) 所以 \(\varphi(p) \mid t\frac{p-1}{2}\),所以 \(t\) 一定是偶数。此时 \(x=g^{\frac{t}{2}}\)。故 \(n\) 是二次剩余。

上面证明了 \(n^{\frac{p-1}{2}}\equiv 1 \iff n\) 是二次剩余。又因为 \(n^{\frac{p-1}{2}}\) 只能等于 \(±1\),所以 \(n^{\frac{p-1}{2}}\equiv -1 \iff n\) 是二次非剩余。

Cipolla

对于方程 \(x^2 \equiv n \pmod p\),先随机选出一个自然数 \(a\),使得 \(a^2-n\) 为二次非剩余,已证二次非剩余有 \(\frac{p-1}{2}\) 个,故而期望 \(2\) 次得到 \(a\)。接下来定义 \(\zeta^2 \equiv a^2 -n \pmod p\)

再给出两个引理:

引理「1」:\(\zeta ^p \equiv -\zeta\)

证明: \(\zeta^p \equiv \zeta\times (\zeta^2)^{\frac{p-1}{2}}\equiv \zeta\times (a^2-n)^{\frac{p-1}{2}}\equiv -\zeta \pmod p\)

引理「2」: \((a+\zeta)^p \equiv a^p+\zeta^p\)

证明:二项式展开,除了 \(a^p\)\(\zeta^p\) 两项外,其他项的系数都是 \(p\) 的倍数。

那么有 \((a+\zeta)^{p+1}\equiv n \pmod p\)

证明如下:

\((a+\zeta)^{p+1}\equiv (a+\zeta)^p(a+\zeta)\),由引理「2」\((a+\zeta)^p(a+\zeta)\equiv (a^p+\zeta^p)(a+\zeta)\),由引理「1」\((a^p+\zeta^p)(a+\zeta)\equiv (a^p-\zeta)(a+\zeta)\)。由费马小定理 \(a^p\equiv a^{p-1}\times a\equiv a \pmod p\),故而 \((a^p-\zeta)(a+\zeta)\equiv (a-\zeta)(a+\zeta)\equiv a^2-\zeta^2\equiv n \pmod p\)

所以 \((a+\zeta)^{\frac{p+1}{2}}\) 是一个解。

现在的问题就是 \((a+\zeta)^{\frac{p+1}{2}}\) 的“虚部”是否为 \(0\)?事实上是不会的。

证明:

假设存在 \((A+B\zeta)^2 \equiv n\)\(B\not = 0\)

那么就有 \(A^2+B^2(a^2-n) -2AB\zeta \equiv0 \pmod p\)

右边“虚部”为 \(0\) 则左边“虚部”一定也为 \(0\)。因为 \(B\not= 0\),所以 \(A\equiv 0\)\((B\zeta)^2\equiv 0\)\(\zeta^2\equiv \dfrac{n}{B^2}\)\(n,\dfrac{1}{B^2}\) 都是二次剩余,乘在一起也一定是二次剩余。所以 \(\zeta^2\) 是二次剩余,与前矛盾。故 \(B=0\),所以 \((a+\zeta)^{\frac{p+1}{2}}\) 的虚部是 \(0\)

模板题代码

#include<bits/stdc++.h>
#define FOR(i,j,k)  for(int i=(j);i<=(k);i++)
using namespace std;
int n,tc,mod;
long long sqr;
struct cplx{
	long long real,imag;
	cplx(long long real=0,long long imag=0):real(real),imag(imag){}
};
inline cplx operator *(cplx x,cplx y)
{
	return cplx((x.real*y.real+sqr*x.imag%mod*y.imag)%mod,(x.imag*y.real+x.real*y.imag)%mod);
}
inline cplx f(cplx x,int y)
{
	cplx res=1;
	while(y)
	{
		if(y&1)	res=res*x;
		x=x*x;y>>=1;
	}
	return res;
}
inline int F(int base,int y)
{
	int res=1,p=base;
	while(y)
	{
		if(y&1)	res=1ll*res*p%mod;
		p=1ll*p*p%mod;y>>=1;
	}
	return res;
}
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
int main()
{
	srand(19260817);
	tc=read();
	while(tc--)
	{
		n=read(),mod=read();
		n%=mod;
		int x=F(n,(mod-1)>>1);
		if(x==mod-1)	puts("Hola!");
		else if(!x)	puts("0");
		else
		{
			x=rand()%mod;
			sqr=0;
			while(!x||F((1ll*x*x+mod-n)%mod,(mod-1)>>1)==1)	x=rand()%mod;
			sqr=(1ll*x*x+mod-n)%mod;
			int ans1=f(cplx(x,1),(mod+1)>>1).real;
			int ans2=mod-ans1;
			if(ans1>ans2)	swap(ans1,ans2);
			printf("%d %d\n",ans1,ans2);
		}	
	}
		
	return 0;
}


BSGS

北上广深好啊。

BSGS(Baby Step Giant Step),大步小步拔山盖世/北上广深算法。常用于求解离散对数问题。

可以在 \(O(\sqrt{p})\) 的时间内求解模方程

\[a^x\equiv c \pmod p \]

其中 \(\gcd(a,p)=1\)。方程的解 \(x\) 满足 \(0\le x\le \varphi(p)\)

算法描述

\(x\) 表示成 \(x=At-B\) 的形式,其中 $0\le A\le \max(t,\frac{p}{t}) $,$0\le B< \max(t,\frac{p}{t}) $,则有 \(a^{At-B}\equiv b \pmod p\),即 \(a^{At}\equiv ba^{B}\pmod p\)

我们 枚举 \(B\),并计算 \(ba^B\) 将其放入 Hash 表中。

然后枚举 \(A\),在 Hash 表中查询 \(a^{At}\) 即可。

时间复杂度为 \(O(\max(t,\frac{p}{t}))\),显然 \(t\)\(\sqrt{p}\) 时最优。因为我懒用 map 实现的 Hash 表,所以最后的复杂度会带 \(1\) 个 log。

代码

P3846 [TJOI2007] 可爱的质数/【模板】BSGS

#include<bits/stdc++.h>
#define FOR(i,j,k)  for(int i=(j);i<=(k);i++)
using namespace std;
int mod,a,b;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
inline int BSGS(int a,int b,int mod)
{
	if(b==1)	return 0;
	int t=ceil(sqrt(mod));
	map<int,int> mp;
	int z=1;
	for(int i=0;i<t;i++)
		mp[1ll*b*z%mod]=i,z=1ll*z*a%mod;
	int p=1;
	for(int i=1;i<=t;i++)
	{
		p=1ll*z*p%mod;
		if(mp.count(p))	return i*t-mp[p];
	}
	return -1;
}
int main()
{
	mod=read(),a=read(),b=read();
	int ans=BSGS(a,b,mod);
	if(ans==-1)	puts("no solution");
	else printf("%d\n",ans);
	return 0;
}

[SDOI2013] 随机数生成器

题目意思是给定 \(a,b,x_1,p,t\) 其中 \(p \in \text{Prime}\)\(0\le a,b,x_1,t<p\)

定义 \(x_i=a\times x_{i-1}+b\),求最小的 \(n\) 使 \(x_n \equiv t \pmod p\)

分析:大力化简。

\[x_1=x_1 \]

\[x_2=a\times x_1 +b \]

\[x_3=a^2 \times x_1 +ab+b \]

\[x_4=a^3\times x_1+a^2b+ab+b \]

我们得出一个很重要的结论: \(x_n=a^{n-1}\times x_1+b\sum\limits_{i=0}^{n-2}a^i\)

发现后面一项是等比数列求和。

\(S=\sum\limits_{i=0}^{n-2}a^i\),则 \(aS=\sum\limits_{i=1}^{n-1}a^i\)\((a-1)S=\sum\limits_{i=1}^{n-1}a^i-\sum\limits_{i=0}^{n-2}a_i=a^{n-1}-1\)

那么 \(S=\dfrac{a^{n-1}-1}{a-1}\)

带入后得到: \(x_n=a^{n-1}\times x_1 +b \dfrac{a^{n-1}-1}{a-1}=a^{n-1}\times x_1+a^{n-1}\dfrac{b}{a-1}-\dfrac{b}{a-1}=a^{n-1}(x_1+\dfrac{b}{a-1})-\dfrac{b}{a-1}\)

那么就有 \(x_n = a^{n-1}(x_1+\dfrac{b}{a-1})-\dfrac{b}{a-1}\equiv t \pmod p\)

\(a^{n-1}\equiv \dfrac{t+\frac{b}{a-1}}{x_1+\frac{b}{a-1}}\)

直接 BSGS 即可。

有亿点点细节。

  • 「1」当 \(x_1=t\) 时,\(n=1\)
  • 「2」当 \(a=0\) 时,\(x_n=0\)
  • 「3」当 \(a=1\) 时,等比数列求不了和, \(x_n=x_1+b(n-1)\equiv t \pmod p\)\(n=\dfrac{t-x_1+b}{b}\)。需要用 Bezout 定理。

code


N 次剩余

求解

\[x^a\equiv b \pmod p \]

其中 \(p\in \text{Prime}\)。(因为不会任意模数)

由于 \(p\) 为质数,则必存在一个原根 \(g\)。因此对于模 \(p\) 意义下的任意数 \(x(1\le x<p )\),都存在有一个数 \(i(0\le i <p-1)\) 满足 \(x=g^i\)

方法一

\(x=g^c\),则问题转化为 \((g^c)^a\equiv b \pmod p\),稍加转换即得 \((g^a)^c \equiv b\pmod p\)。这不就是我们的 BSGS 所干的事情吗?

可以 \(O(\sqrt{p})\) 求出一个特解 \(x_0 \equiv g^c \pmod p\)

方法二

\(x=g^c\),设 \(b=g^t\),于是有 \(g^{ac}\equiv g^t\pmod p\)。由阶的性质的 \(ac\equiv t \pmod {\varphi(p)}\)。其中 \(t\) 可以在 \(O(\sqrt{q})\) 内求出。于是就转化成了 exgcd 所做的事情。这样可以求出一个特解 \(c_0\),其通解为 \(c_0+k \dfrac{\varphi(p)}{\gcd(a,\varphi(p))}\),其中 \(k\) 是整数。可以用 vector 记录一下,用 Hash 表判重。


exBSGS

同样是求解

\[a^x\equiv b \pmod p \]

不过此时 \(a,p\) 不一定互质。我们可以想办法让她们互质。

具体地,设 \(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}\) 仍不互质就继续重复上面的步骤,直到 \(\displaystyle \gcd\left(a,\frac{p}{\prod _{i=1}^{k} d_i}\right )\)

\(D=\prod \limits_{i=1}^k d_i\),原方程被化为了:

\[\frac {a^k}{D}\times a^{x-k}\equiv \frac{b}{D}\pmod {\frac{p}{D}} \]

此时 \(\gcd \left( \dfrac{a^k}{D},p\right)=1\),故 \(\dfrac{a^k}{D}\) 存在逆元,可以丢到式子右边。

这就是一个平凡的 BSGS 了。求解出 \(x-k\) 再加上 \(k\) 就是原方程的解。

有可能存在 \(x\le k\) 的情况。我们在消去因子前先 \(O(k)\) 枚举一下即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b,p;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int exgcd(int a,int b,int &x,int &y)
{
	if(!b)
	{
		x=1,y=0;
		return a;
	}
	int gcd=exgcd(b,a%b,y,x);
	y-=(a/b)*x;
	return gcd;
}
inline int exBSGS(int a,int b,int mod)
{
	b%=mod;
	if(b==1||mod==1)	return 0;
	int g=0,val=1;
	while(true)
	{
		int d=gcd(a,mod);
		if(d==1)	break;
		if(b%d)	return -1;
		b/=d,mod/=d,val=val*a/d%mod;
		g++;
		if(b==val)	return g;
	}
	int x,y;
	exgcd(val,mod,x,y);
	x=(x%mod+mod)%mod;
	b=b*x%mod,a%=mod;
	map<int,int>mp;
	int t=ceil(sqrt(mod));
	int z=1;
	for(int i=0;i<t;i++)
		mp[b*z%mod]=i,z=z*a%mod;
	int p=1;
	for(int i=1;i<=t;i++)
	{
		p=p*z%mod;
		if(mp.count(p))	return i*t-mp[p]+g;
	}
	return -1;
}
signed main()
{
	a=read(),p=read(),b=read();
	while(a||b||p)
	{
		int ans=exBSGS(a,b,p);
		if(ans==-1)	puts("No Solution");
		else	printf("%lld\n",ans);
		a=read(),p=read(),b=read();
	}
	return 0;
}


Lucas

内容

\(p\in \text{Prime}\)\(a,b\in \mathbb{N}^*\)。并且 \(a=\sum\limits _{i=0}^k m_ip^i,b=\sum\limits_{i=0}^{k}n_ip_i\)

则有 \(C_b^a \equiv \prod \limits_{i=0}^k C_{m_i}^{n_i} \pmod p\)

注意:若 \(n_i>m_i\)\(C_{m_i}^{n_i}=0\)

然而我们一般使用的以下的这个式子:

\[C_b^a\equiv C_{\lfloor b/p\rfloor}^{\lfloor a/p \rfloor}\times C_{b \bmod p}^{a \bmod p}\pmod p \]

证明

(以下运算默认在模 \(p\) 意义下进行)

先证一个引理:

\((a+b)^p \equiv a^p+b^p \pmod p\)

我们考虑二项式展开,除了第一项和最后一项,其他项都含有 \(p\),故都被模没了。只剩下 \(a^p\)\(b^p\)

我们设 \(a=\lfloor \frac{a}{p}\rfloor \times p +a\bmod p\)\(a'=\lfloor \frac{a}{p}\rfloor\)

则有:

\((1+x)^a=(1+x)^{\lfloor \frac{a}{p}\rfloor \times p +a\bmod p}=(1+x)^{a'\times p+a\bmod p}=(1+x)^{a'p}(1+x)^{a \bmod p}\)

因为 \(a \bmod p=m_0\),所以 \((1+x)^{a'p}(1+x)^{a \bmod p}=((1+x)^p)^{a'}(1+x)^{m_0}=(1+x^p)^{a'}(1+x)^{m_0}\)

再设 \(a'=\lfloor \frac{a'}{p}\rfloor \times p +a'\bmod p\)\(a''=\lfloor \frac{a'}{p}\rfloor\)。重复上述推导,得: \((1+{x^p}^2)^{a''}(1+x^p)^{m_1}\)

就这样一直推下去直到

\[(1+x)^a=(1+{x^p}^k)^{m_k}\times (1+x^{p^{k-1}})^{m_{k-1}}\times \cdots\times(1+x)^{m_0} \]

对左右两边分别使用二项式定理求 \(x^b\)。右边的每一项为 \(b\)\(p\) 进制下对应的每一个数。

\[C_a^b x^b=C_{m_k}^{n_k}x^{p_kn_k}\times C_{m_{k-1}}^{n_{k-1}}x^{p_{k-1}n_{k-1}}\times\cdots\times C_{m_0}^{n_0}x^{p_0n_0}=(\prod_{i=0}^k C_{m_i}^{n_i})(x^{\sum _{i=0}^{k}p_in_i})=x^b (\prod _{i=0}^k C_{m_i}^{n_i}) \]

同除 \(x^b\) 即得。

当然也可以写成:(这不就是求一个数在 \(p\) 进制下的表示的过程吗)

\[C_b^a\equiv C_{\lfloor b/p\rfloor}^{\lfloor a/p \rfloor}\times C_{b \bmod p}^{a \bmod p}\pmod p \]

模板题

code


exLucas

跟 Lucas 并没有关系的说。

前置芝士

  • CRT
  • exgcd
  • 组合数

和 Lucas 求解的是一类问题,不过 exLucas 不要求模数为质数。

由于 \(p \not \in \text{Prime}\),考虑对其质因数分解

\[p=\prod_{i=1}^k p_i^{q_i} \]

分解以后,我们只要求出 \(C_m^n\bmod p_i^{a_i}\) 的值,就可以用 CRT 合并出最终答案。

下面来考虑 \(C_m^n \bmod p^{a}\),我们都知道 \(C_m^n=\dfrac{m!}{n!\times(m-n)!}\)。但是此时 \(p^{a}\) 不一定与 \(n!,(m-n)!\) 互质,这样就没法求逆元了。我们考虑对于将这些阶乘中的 \(p_i\) 提出来,就变成了

\[\frac{\frac{m!}{p^x}}{\frac{n!}{p^y}\times\frac{(m-n)!}{p^z}}\times p^{x-y-z} \]

其中 \(\dfrac{n!}{p^y}\)\(\dfrac{(m-n)!}{p^z}\)\(p^a\) 互质,可以直接求逆元。

下面我们来考虑计算形如 \(\dfrac{n!}{p^x}\bmod p^a\) 的式子。

先看 \(n! \bmod p^a\)

举个例子: \(n=22,p=3,a=2\)。(网上举得基本上都是这个例子)

\(22!=1\times 2\times 3\times 4\times 5\times 6\times 7\times 8\times 9\times 10\times 11\times 12\times 13\times 14\times 15\times 16\times 17\times 18\times 19\times 20\times 21\times 22\)

把所有 \(p\) 的倍数提出来,得到:

\[n!=p^{\lfloor \frac{n}{p}\rfloor}\times \lfloor\frac np\rfloor! \times \prod_{p\nmid i}^n i \]

还是那个例子:

\(22!=3^7\times \begin{matrix}\underbrace{(1\times 2\times 3\times 4\times 5\times 6\times 7)}\\\text{这些就是原先 3 的倍数}\end{matrix}\times(1×2×4×5×7×8×10×11×13×14×16×17×19×20×22)\)

因为 \(x\equiv x+p^a \pmod {p^a}\),所以我们发现最后一部分是循环的。

具体到例子里:\(1×2×4×5×7×8≡10×11×13×14×16×17 \pmod {3^2}\)

我们先暴力搞一个循环,然后快速幂计算其 \(\lfloor \frac n{p^a}\rfloor\) 幂。还剩下不能构成循环的最后几项,暴力乘一下。

这样三部分的乘积就是 \(n!\),最终还要除以一个 \(p^x\)。第一部分被约掉,不用管了。第二部分可以递归计算,过程中自然把 \(p\) 因子除去,故而最终答案就是第二部分递归后的结果与第三部分的乘积。

然后就可以计算了。

最后 CRT 合并即可。

模板题

code


狄利克雷卷积 Dirichlet Product

Link.


莫比乌斯反演

Link.


类欧几里得


\(\mathfrak{To}\) \(\mathfrak{Be}\) \(\mathfrak{Continued...}\)

posted @ 2021-08-18 21:21  LJC001151  阅读(171)  评论(0)    收藏  举报