声明
在本文中,
- \(a\mid b\) 表示 \(b\bmod a=0\)
- \(a\nmid b\) 表示 \(b\bmod a\not=0\)
- \(\sum\) 表示求和
- \(\prod\) 表示求积
- \(a!\) 表示 \(a\) 的阶乘
- \(\left\lfloor\dfrac{a}{b}\right\rfloor\) 表示下取整 \(\dfrac{a}{b}\)
- \(\left\lceil\dfrac{a}{b}\right\rceil\) 表示上取整 \(\dfrac{a}{b}\)
- \(\gcd(),\operatorname{lcm}()\),分别表示最大公约数和最小公倍数
- \(a\perp b\) 指 \(\gcd(a,b)=1\)
- \(a\gets b\) 表示使 \(a\) 变为 \(b\)
- \(a\in A\) 表示 \(a\) 在集合 \(A\) 内
Eazy
同余方程
定义
若 \(a\bmod m=b\bmod m\),那么称 \(a,b\) 对模 \(m\) 同余,记为 \(a\equiv b\pmod m\)。
逆元
若 \(p\) 与 \(a\) 互质 且 \(ax\equiv 1\pmod p\),则称 \(x\) 是 \(a\) 在模 \(p\) 意义下的逆元,一般记为 \(a^{-1}\)。
容易发现,若有 \(0<b<p\) 为 \(a^{-1}\),则对于任意的 \(0<i\le \infty\) 皆有 \(bi\) 为 \(a^{-1}\)。一般所说的逆元为最小的 \(b\)。
费马小定理
若 \(p\) 是与 \(a\) 互质的质数,则有 \(a^{p-1}\equiv 1\pmod p\)。
证明
构造数集 \(A=\{1,2,\dots,p-1\}\)。
证明:\(\prod_{i=1}^{p-1}a\times A_i\equiv \prod_{i=1}^{p-1}A_i\pmod p\)。
若有 \(aA_i\bmod p=aA_j\bmod p=r(1\le i<j\le p-1)\),设 \(aA_i=xp+r,aA_j=yp+r\),两式相减得 \((A_i-A_j)a=(x-y)p\)。由于 \(a,p\) 互质且 \(A_i-A_j<p\) 所以该等式不成立,故每个 \(aA_i\) 模 \(p\) 的值都是独一无二的,又因为余数只有 \(p-1\) 个,故余数集必为 \(A\) 的一个排列,于是 \(\prod_{i=1}^{p-1}a\times A_i\equiv \prod_{i=1}^{p-1}A_i\pmod p\) 得证。
将左边的 \(a\) 提取出来,得 \(a^{p-1}\prod_{i=1}^{p-1}A_i\equiv \prod_{i=1}^{p-1}A_i\pmod p\),化简得 \(a^{p-1}\equiv 1\pmod p\)。
费马小定理求逆元
因为有 \(a^{p-1}\equiv p\pmod p\),可得 \(a\times a^{p-2}\equiv p\pmod p\),对比逆元的式子 \(ax\equiv 1\pmod p\) 容易发现 \(x=a^{p-2}\),注意这里的 \(x\) 不一定 \(a\) 模 \(p\) 意义下的最小逆元。
注意到有些非质数的数同样满足该定理,例如 \(341=11\times 13\),这样的数被称为伪素数。
剩余系
剩余类
对于任意的一个数 \(n\),根据 \(a\bmod p\) 的不同,可以把 \(a\) 分为 \(n\) 个剩余类,余数为 \(r\) 的类表示为 \(C_r=xp+r\)。
完全剩余系(完系)
从 \(n\) 的每个剩余类中各取出一个元素,这些元素组成了模 \(n\) 的完系。
简化剩余系(缩系)
对于 \(\varphi(n)\) 个与 \(n\) 互质 的 \(r\),在这 \(\varphi(n)\) 个 \(C_r\) 中各取一个元素,组成了模 \(n\) 的缩系。
这里 \(\varphi(n)\) 是指与 \(n\) 互质且 \(<n\) 的正整数的个数,在 筛法与函数-筛法求欧拉函数
一节详细介绍。
威尔逊定理
\((p-1)!\equiv -1\pmod p\) 是 \(p\) 为质数的 充分必要条件。
必要性
若 \(p\) 为质数。
构造模 \(p\) 的 缩系 \(A=\{1,2,\dots,p-1\}\)。
取一个 \(a\in[1,p-1]\),因为 \(a,p\) 互质,故 \(\{a,2a,\dots,ap-a\}\) 也为模 \(p\) 的 缩系,因此只存在一个 \(x\in[1,p-1]\) 使得 \(ax\equiv 1\pmod p\)。
- 若 \(a=x\),则有 \(x^2\equiv 1\pmod p\),因式分解得 \((x+1)(x-1)\equiv 0\pmod p\),因为 \(x,p\) 互质,则 \(x=1\) 或 \(x=p-1\)。
- 若 \(a\not=x\),则有 \(2\le a,x\le p-2\),由于每个 \(a\) 对应着唯一的 \(x\) ,所以有 \(\dfrac{p-2-2+1}{2}=\dfrac{p-3}{2}\) 对 \(a,x\) 使得 \(ax\equiv 1\pmod p\),将所有这样的式子乘起来就能得到 \((p-2)!\equiv 1\pmod p\),两边同乘 \(p-1\) 得 \((p-1)!\equiv 1\pmod p\),即 \((p-1)!\equiv -1\pmod p\)。
充分性
若 \(p\) 为合数。
当 \(p=1\) 时,\((1-1)!\equiv 0\pmod 1\)
当 \(p=4\) 时,\((4-1)!\equiv 2\pmod 4\)
当 \(p>4\) 时,
- 若 \(p\) 不是完全平方数,构造 \(2\le a<b< p\),
则有 \((p-1)!=1\times2\times\dots\times a\times\dots\times b\times\dots\times p-1=kp\),有 \((p-1)!\equiv 0\pmod p\)。 - 若 \(p\) 是完全平方数,构造 \(p=k^2\),
则有 \((p-1)!=1\times2\times\dots\times k\times\dots\times 2k\times\dots\times p-1=kp\),有 \((p-1)!\equiv 0\pmod p\)。
推论
若 \(p\) 为质数,则 \((p-1)!+1\equiv 0\pmod p\)。
若 \(p>4\) 且 \(p\) 为合数,则 \((p-1)!\equiv 0\pmod p\)。
e.g. 给定 \(n\),求 \(S=\sum_{p=1}^{n}\left\lfloor\dfrac{(p-1)!+1}{p}-\left\lfloor\dfrac{(p-1)!}{p}\right\rfloor\right\rfloor\)。
若 \(p\) 为质数,则 \(\dfrac{(p-1)!+1}{p}\) 为整数,\(S=1\)。
否则 \(\dfrac{(p-1)!+1}{p}=\left\lfloor\dfrac{(p-1)!}{p}\right\rfloor\),\(S=0\)。
筛出 \(\in[1,n]\) 的质数即可。
欧拉定理
若 \(a,m\) 互质,则有 \(a^{\varphi(m)}\equiv 1\pmod m\)。
证明
设 \(k=\varphi(m)\)。
构造模 \(m\) 的缩系 \(\{r_1,r_2,\dots,r_k\}\)。
因为 \(a,m\) 互质,所以 \(\{ar_1,ar_2,\dots,ar_k\}\) 也是 \(m\) 的一个缩系,则有 \(\prod_{i=1}^k r_i\equiv\prod_{i=1}^k ar_i\equiv a^k\times\prod_{i=1}^k r_i\pmod m\),约去 \(\prod_{i=1}^k r_i\) 可得 \(a^k\equiv 1\pmod m\)。
用欧拉定理证费马小定理
当 \(m\) 为质数时,\(\varphi(m)=m-1\),则有 \(a^{m-1}\equiv 1\pmod m\)。
扩展欧拉定理
对于 任意 的 \(a,b,m\),有:
e.g. 模版。
观察到 \(b\) 很大,将 \(b\) 降幂后再快速幂即可。
int gphi(int m) {long long s=m;for(int i=2;i*i<=m;i++) {if(m%i==0) {s=s/i*(i-1);while(m%i==0) m/=i;}}if(m>1) s=s/m*(m-1);return s;
}
void cele(int mod) {bool fl=false;for(int i=0;i<s.size();i++) {b=(b*10+(s[i]-'0'));if(b>mod) b%=mod,fl=true;}if(fl) b+=mod;
}
long long qpow(long long a,int b,int mod) {long long ans=1;while(b) {if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans%mod;
}
连续逆元线性求
模版。
当前已知 \(1\sim i-1\) 的逆元,要求 \(i(i>1)\) 在模 \(p\) 意义下的逆元。
设 \(p=ki+r(0\le r<i)\),则有 \(ki+r\equiv 0\pmod p\),两边同乘 \(i^{-1}r^{-1}\) 得 \(kr^{-1}+i^{-1}\equiv 0\pmod p\),移项得 \(i^{-1}\equiv -kr^{-1}\equiv -\left\lfloor\frac{p}{i}\right\rfloor\times (p \bmod i)^{-1}\pmod p\)。
于是就求出了 \(i\) 的逆元。
for(int i=2;i<=n;i++) {a[i]=((p-p/i)*a[p%i])%p;//注意可能是负数,把 p/i 变为 p-p/i 以去掉负号printf("%lld\n",a[i]);
}
不定方程(组)
定义
若未知数的个数大于方程的个数,则该方程(组)被称为不定方程(组)。
不定方程(组)一般有无数个解,所以题目会对未知数有一些约束条件。
裴蜀定理
一定存在 \(x,y\) 满足 \(ax+by=\gcd(a,b)\)。
该定理对不定方程是否有整数解做出了一个判定方式。
证明
设取整数 \(x_0,y_0\) 时,\(ax_0+by_0=m\),\(\gcd(a,b)=k\),\(m\) 为满足条件的最小正整数。
现在要证 \(m=k\)。
因为 \(x_0,y_0\) 为整数,所以有 \(k\mid ax_0,k\mid by_0\),则 \(k\mid ax_0+by_0\),得 \(k\mid m\) (1)。
设 \(a=qm+r(0\le r<m)\),则有
因为 \(qx_0,qy_0\) 均为整数,所以可以使 \(x=1-qx_0,y=-qy_0,r=ax+by\)。
由于 \(r<m\) 且 \(m\) 是满足条件的最小正整数,所以 \(r=0,a=qm\),因此 \(m\mid a\),同理得 \(m\mid b\),故 \(m\mid k\) (2)。
综合 (1)(2) 得:\(m=k\) 得证。
简单思考一下可以发现,若 \(ax'+by'=k\times\gcd(a,b)\),则 \(x',y'\),变为原解的 \(k\) 倍即可,故形如 \(ax+by=c\) 的不定方程只要满足 \(c=k\times\gcd(a,b)\) 就有整数解,\(k\) 为整数。
同理可得,\(n\) 个未知数的不定方程 \(\sum_{i=1}^{n} a_ix_i=s\) 满足 \(s=k\times\gcd(a_i)\) 时有整数解。
e.g. 模版。
根据上面的结论求出 \(\gcd(\left|A_i\right|)\) 即可。
for(int i=1;i<=n;i++) {cin>>a;if(a<0) a=-a;ans=G(ans,a);
}
扩展欧几里得算法
欧几里得算法
\(\gcd(a,b)=\gcd(b,a\bmod b)\)
没错,就是这个。
从辗转相除法到不定方程
求 \(ax+by=\gcd(a,b)\) 的整数解。
上面我们已经论证了该方程有整数解,这里使用扩展欧几里得算法求解。
所以有 \(x=y_1,y=x_1-\left\lfloor\frac{a}{b}\right\rfloor y_1\)。
注意到 \(b=0\) 时 \(x=1,y=0\),故递归到下界 \(b=0\) 解决即可得到一组 特解。
long long exgcd(long long a,long long b,long long &x,long long &y) {if(b==0) {x=1,y=0;return a;}long long d,x1,y1;d=exgcd(b,a%b,x1,y1);x=y1,y=x1-a/b*y1;return d;
}
从特解到通解
考虑同时使 \(ax\gets ax+k\) 和 \(by\gets by-k\) 来构造通解。
故有 \(x'=x+k\times\dfrac{b}{\gcd(a,b)},y'=y-k\times\dfrac{a}{\gcd(a,b)}\)。
从不定方程到同余方程
求 \(ax\equiv b\pmod m(0\le b<m)\) 的整数解。
设 \(ax=-ym+b\),则有 \(ax+ym=b\)。根据裴蜀定理判断该方程是否有整数解,然后用扩展欧几里得计算即可。
e.g. 并非模版。
设 \(m=19260817\)。
将同余方程化为 \(bx+ym=a\) 求解即可。
Another Idea:求 \(b^{-1}\),就有 \(bb^{-1}\equiv 1\pmod m\),两边同乘 \(a\) 得 \(b\times(ab^{-1})\equiv a\pmod m\),所以 \(x=ab^{-1}\)。
中国剩余定理
模版。
即要求
中 \(x\) 的解。其中 \(m\) 是 两两互质的整数,\(0\le p_i<m_i\)。
中国剩余定理解法
1.设 \(M=\prod_{i=1}^n m_i\)
2.设 \(c_i=\dfrac{M}{m_i}\)
3.计算 \(c_i\) 在模 \(m_i\) 意义下的逆元 \(c_i^{-1}\)
4.\(x=(\sum_{i=1}^na_ic_ic_i^{-1})\bmod M\)
证明
由于 \((\sum_{i=1}^na_ic_ic_i^{-1})\bmod M\) 对于 \(m_i\) 只是减去了它的若干倍,对余数没有影响,所以只需要证 \(x=\sum_{i=1}^na_ic_ic_i^{-1}\) 使同余方程组成立。
- 当 \(i\not=j\) 时,因为 \(c_j=\dfrac{M}{m_j}\) 中包含项 \(m_i\),故 \(c_j\equiv 0\pmod {m_i},c_jc_j^{-1}\equiv 0\pmod {m_i}\)
- 当 \(i=j\) 时,因为 \(c_i=\dfrac{M}{m_i}\) 不含 \(m_i\) 且 \(m\) 两两互质,所以 \(c_i\not\equiv 0\pmod {m_i},c_ic_i^{-1}\equiv 1\pmod {m_i}\)
故 \(x=(\sum_{i=1}^na_ic_ic_i^{-1})\bmod m_i=a_ic_ic_i^{-1}=a_i,x\equiv a_i\pmod {m_i}\)。
long long crt() {long long M=1,ans=0;for(int i=1;i<=n;i++) M*=m[i];for(int i=1;i<=n;i++) {long long c=M/m[i],x,y;exgcd(c,m[i],x,y);ans=(ans+(c*x*a[i])%M)%M;}return (ans%M+M)%M;
}
扩展中国剩余定理
模版。
你猜同余方程的内容为什么会出现在不定方程里。
相较于中国剩余定理,本题 \(m\) 不一定两两互质。
扩展中国剩余定理解法
合并同余方程求解。
将前两个同余方程化为 \(x=m_1p+a_1=m_2q+a_2\)。则有 \(m_1p-m_2q=a_2-a_1\)。
可以用裴蜀定理判断是否有解,使用扩展欧几里得算法求解。
所以有通解 \(p'=p+\frac{m_2}{\gcd(m_1,m_2)}\),代入得 \(x=m_1p+\frac{m_1m_2}{\gcd(m_1,m_2)}+a_1=\operatorname{lcm}(m_1,m_2)+m_1p+a_1\),将 \(m_1p+a_1\) 视作余数即可将两个同余方程合并为 \(x\equiv m_1p+a_1\pmod{\operatorname{lcm}(m_1,m_2)}\)。
合并 \(n-1\) 次即可。正确性显然。
long long mul(long long a,long long b,long long mod) {long long ans=0;while(b>0) {if(b&1) ans=(ans+a)%mod;a=(a+a)%mod;b>>=1;}return ans;
}
long long excrt() {long long m1,m2,a1,a2;m1=m[1],a1=a[1];for(int i=2;i<=n;i++) {m2=m[i],a2=a[i];long long p,q;long long d=exgcd(m1,m2,p,q);//注意这里 a2-a1 并非是 gcd(m1,m2)
// if((a2-a1)%d) return -1;裴蜀定理判断是否有解,这里不用 long long k=m2/d,c=(((a2-a1)/d)%m2+m2)%m2;p=mul(p,c,k);//a2-a1 是 gcd(m1,m2) 的倍数,这里求出正确的特解p=(p%k+k)%k;//保证最小a1=m1*p+a1,m1=m1*(m2/d);a1%=m1;}return (a1%m1+m1)%m1;
}
BSGS
模版。
BSGS(Baby Step Gaint Step),大步小步算法,用于求解 \(a,p\) 互质 的同余方程 \(a^x\equiv b\pmod p\)。
求解方法
由扩展欧拉定理 \(a^x\equiv a^{x\bmod\varphi(p)}\pmod p\) 得 \(a^x\) 模 \(p\) 意义下的最小循环节为 \(\varphi(p)\),由于 \(\varphi(p)<p\),所以可以暴力枚举 \(x=0\sim p\),时间复杂度 \(O(p)\)。
令 \(x=im-j\),\(m=\left\lceil\sqrt n\right\rceil,1\le i\le m,0\le j\le m-1\),显然任意的 \(x\in [0,p]\) 均可被表示出来。
则有 \(a^{im-j}\equiv b\pmod p,(a^m)^i\equiv ba^j\pmod p\)。
- 枚举 \(j\),将 \(\operatorname{key}=ba^j\bmod p,\operatorname{val}=j\) 放入哈希表,若 \(\operatorname{key}\) 重复则用大的 \(j\) 替换小的。
- 枚举 \(i\),查找是否有 \(\operatorname{key}=(a^m)^i\),有则 \(x=im-j\)。
由于 \(i,i\le \left\lceil\sqrt p\right\rceil\),所以时间复杂度为 \(O(\sqrt p)\)。正确性显然。
long long a,b,p;
map<long long,long long> mp;
long long bsgs() {long long m=sqrt(p);if(m*m!=p) m++;mp[b]=0;for(long long i=1;i<m;i++) {b=(b*a)%p;mp[b]=i;}long long k=1;for(int i=1;i<=m;i++) k=(k*a)%p;long long i,j,t=1;for(i=1;i<=m;i++) {t=(t*k)%p;if(mp.count(t)) return i*m-mp[t];}return -1;
}
为什么要求 \(a,p\) 互质
\(a^{im-j}\equiv b\pmod p,(a^m)^i\equiv ba^j\pmod p\) 中,若 \(a,p\) 不互质,则两边同乘 \(0\),后面就没有意义了。
扩展 BSGS
模版。
你猜同余方程的内容为什么会出现在不定方程里。
相较于 BSGS,本题 \(a,p\) 不互质。
求解方法
将同余方程 \(a^x\equiv b\pmod p\) 化为 \(a\times a^{x-1}\equiv b\pmod p\),进一步变为不定方程 \(a\times a^{x-1}+py=b\),将 \(a,p\) 视为常数,设 \(d=\gcd(a,p)\),则若 \(d\nmid b\),方程无解,否则将 同余方程 两边同除 \(d\),得 \(\dfrac{a}{d}a^{x-1}\equiv \dfrac{b}{d}\pmod{\dfrac{p}{d}}\),记 \(p'=\dfrac{p}{d}\),若 \(\gcd(a,p')\not=1\) 则继续直到 \(a\perp p'\)。记 \(D=\dfrac{p}{p'}\),共进行了 \(k\) 次,则 \(\dfrac{a^k}{D}a^{x-k}\equiv b\pmod {p'}\),由于有 \(a\perp p'\),所以有 \(\dfrac{a^k}{D}\perp p'\),两边同乘它的逆元后就变为了 BSGS。
long long bsgs(int A) {long long m=sqrt(p);if(m*m!=p) m++;mp[b]=0;for(long long i=1;i<m;i++) {b=(b*a)%p;mp[b]=i;}long long k=1;for(int i=1;i<=m;i++) k=(k*a)%p;long long i,j,t=A;//注意这里 t 从 a^k/D 开始for(i=1;i<=m;i++) {t=(t*k)%p;if(mp.count(t)) return i*m-mp[t];}return -1;
}
long long exbsgs() {if(b==1||p==1) return 0;long long d,k=0,A=1;while(true) {d=gcd(a,p);if(d==1) break;if(b%d) return -1;k++,b/=d,p/=d,A=(A*(a/d))%p;if(A==b) return k;}long long ans=bsgs(A);if(ans==-1) return -1;else return ans+k;//记得算出来的是 x-k 要加 k
}
筛法与函数
筛质数
模版。
埃氏筛
从小到大枚举,若当前数未被标记,则为质数,标记其倍数。
void ess(int n) {for(int i=2;i<=n;++i) {if(!vis[i]){pr[++cnt]=i;for(int j=i*i;j<=n;j+=i) vis[j]=1;}}
}
欧拉筛
从小到大枚举,若未被标记,则为质数,对 每个数 \(i\) 枚举 \(j\) 到其 最小质因子,标记 \(ij\)。
void ols(int n) {for(int i=2;i<=n;i++) {if(!vis[i]) pr[++cnt]=i;for(int j=1;i*pr[j]<=n;j++) {vis[i*pr[j]]=1;if(i%pr[j]==0) break;}}
}
筛法求欧拉函数
欧拉函数
欧拉函数即 \(\varphi(n)\),被定义为 \(1\sim n\) 中与 \(n\) 互质的数的个数。
特性:
1.若 \(p\) 是质数,则 \(\varphi(p)=p-1\)
2.若 \(p\) 是质数,则 \(\varphi(p^k)=p^{k-1}\varphi(p)\)(证明:由于 \(p\) 是质数,则 \(1\sim p-1,p+1\sim 2p-1,\dots,p^k-p\sim p^{k}-1\) 均与 \(p\) 互质,共有 \(p^{k-1}\) 节长度为 \(\varphi(p)\) 的区间,故 \(\varphi(p^k)=p^{k-1}\varphi(p)\))
3.积性函数:若 \(p,q\) 互质,则有 \(\varphi(pq)=\varphi(p)\varphi(q)\)(证明参考 剩余系的复合)
计算
有 \(\varphi(n)=n\prod_{i=1}^s\dfrac{p_i-1}{p_i}\),\(s\) 为质因子个数,\(p_i\) 为不同的质因子。证明参考性质 2,3。
试除法找质因子即可。
int gphi(int m) {long long s=m;for(int i=2;i*i<=m;i++) {if(m%i==0) {s=s/i*(i-1);while(m%i==0) m/=i;}}if(m>1) s=s/m*(m-1);return s;
}
筛法计算
若 \(i\) 是质数,则 \(\varphi(i)=i-1\)。
若 \(i\) 是合数,则 \(i\) 在线性筛中被自己的 最小质因子 筛掉。
设 \(n\) 为 \(i\) 的最小质因子,\(i=nm\)。
- 若 \(n\mid m\),则 \(m\) 包含 \(i\) 的所有质因子,\(nm\prod_{k=1}^s\dfrac{p_k-1}{p_k}=n\varphi(m)\)
- 若 \(n\nmid m\),则 \(n,m\) 互质,由性质 1,3,得 \(\varphi(i)=\varphi(n)\varphi(m)=(n-1)\varphi(m)\)。
void get_phi(int n) {phi[1]=1;for(int i=2;i<=n;i++) {if(!vis[i]) {p[cnt++]=i;phi[i]=i-1;}for(int j=0;i*p[j]<=n;j++) {int m=i*p[j];vis[m]=1;if(i%p[j]==0) {phi[m]=p[j]*phi[i];break;} else phi[m]=(p[j]-1)*phi[i];}}
}
筛法求莫比乌斯函数
莫比乌斯函数
根据唯一分解定理,有 \(x=\prod_{i=1}^s p_i^{a_i}\),其中 \(p_i\) 为互不相同的质因子,\(s\) 为质因子个数。
则有
其中 \(\sum_{i-1}^s a_i=s\) 的条件即 \(x\) 不含相同质因子。
筛法计算
若 \(i\) 是质数,则 \(\mu(i)=1\)。
若 \(i\) 是合数,则 \(i\) 在线性筛中被自己的 最小质因子 筛掉。
设 \(n\) 为 \(i\) 的最小质因子,\(i=nm\)。
- 若 \(n\mid m\),则 \(i\) 有两个质因子 \(n\),\(\mu(i)=0\)
- 若 \(n\nmid m\),则 \(i\) 比 \(m\) 多一个质因子 \(n\),\(\mu(i)=-\mu(m)\)
void get_mu(int n) {mu[1]=1;for(int i=2;i<=n;i++) {if(!vis[i]) {p[++cnt]=i;mu[i]=-1;}for(int j=1;i*p[j]<=n;j++) {int m=i*p[j];vis[m]=1;if(i%p[j]==0) {mu[m]=0;break;} else mu[m]=-mu[i];}}
}
约数相关
根据唯一分解定理,有 \(x=\prod_{i=1}^s p_i^{a_i}\),其中 \(p_i\) 为互不相同的质因子,\(s\) 为质因子个数。
约数和定理
\(x\) 的约数和 \(f(x)=\prod_{i=1}^s\sum_{j=0}^{a_i}p_i^j\)。
证明:\(p_i^{a_i}\) 的约数有 \(p_i^0,p_i^1,\dots,p_i^{a_i}\) 共 \((a_i+1)\) 个,约数和为 \(\sum_{j=0}^{a_i}p_i^j\),根据乘法原理 \(x\) 有 \(f(x)=\prod_{i=1}^s\sum_{j=0}^{a_i}p_i^j\) 个约数。
筛法求约数和
记 \(p_j\) 为 \(i\) 的最小质因子,\(g(i)=\sum_{i=1}^{a_j} p_j^i\)
若 \(i\) 是质数,则 \(f(i)=g(i)=i+1\)。
若 \(i\) 是合数,则 \(i\) 在线性筛中被自己的 最小质因子 筛掉。
设 \(i=p_jm\)。
- 若 \(p_j\mid m\),则 \(m\) 的最小质因子也一定是 \(p_j\),但 \(i\) 的 \(p_j\) 的次数要比 \(m\) 多一,故 \(g(i)=g(m)+p_j^{a_j+1},f(i)=f(m)\div g(m)\times g(i)\)
- 若 \(p_j\nmid m\),则 \(m\) 不包含质因子 \(p_j\),\(g(i)=p_j+1,f(i)=f(m)\times g(i)\)。
void get_f(int n) {g[1]=f[1]=1;for(int i=2;i<=n;i++) {if(!vis[i]) {p[++cnt]=i;g[i]=f[i]=i+1;}for(int j=1;i*p[j]<=n;j++) {intm=i*p[j];vis[m]=1;if(i%p[j]==0) {g[m]=g[i]*p[j]+1;f[m]=f[i]/g[i]*g[m];break;} else {g[m]=p[j]+1;f[m]=f[i]*g[m];}}}
}
约数个数定理
\(x\) 的约数个数 \(d(x)=\prod_{i=1}^s(a_i+1)\)。
证明同约数和定理。
筛法求约数个数
记 \(a_i\) 为 \(i\) 最小质因子次数。
若 \(i\) 是质数,则 \(d(i)=2,a_i=1\)。
若 \(i\) 是合数,则 \(i\) 在线性筛中被自己的 最小质因子 筛掉。
设 \(i\) 的最小质因子是 \(p_j\),\(i=p_jm\)。
- 若 \(p_j\mid m\),则 \(m\) 的最小质因子也一定是 \(p_j\),但 \(i\) 的 \(p_j\) 的次数要比 \(m\) 多一,故 \(a_i=a_m+1,d(i)=d(m)\div(a_i+1)\times(a_m+1)\)
- 若 \(p_j\nmid m\),则 \(m\) 不包含质因子 \(p_j\),\(a_i=1,d(i)=d(m)\times 2\)。
void get_d(int n) {d[1]=1;for(int i=2;i<=n;i++) {if(!vis[i]) {p[++cnt]=i;a[i]=1;d[i]=2;}for(int j=1;i*p[j]<=n;j++) {int m=i*p[j];vis[m]=1;if(i%p[j]==0) {a[m]=a[i]+1;d[m]=d[i]/(a[i]+1)*(a[m]+1);break;} else {a[m]=1;d[m]=d[i]*2;}}}
}
Hard
矩阵
定义
由 \(m\) 行 \(n\) 列数组成的数组被称为 \(m\times n\) 矩阵。
一个 \(m\times n\) 矩阵 \(A=\begin{bmatrix}A_{1,1}&A_{1,2}&\dots&A_{1,n}\\A_{2,1}&A_{2,2}&\dots&A_{2,n}\\\vdots&\ddots&\ddots&\vdots\\A_{m,1}&A_{m,2}&\dots&A_{m,n}\end{bmatrix}\)
若 \(m=n\),则也可以称为 \(n\) 阶方阵。
若一个 \(n\) 阶方阵 \(A\) 满足 \(A_{i,j}=[i=j]\),则称其为 \(n\) 阶单位矩阵。
矩阵加法
只有 同型矩阵 才有加法。
若 \(A,B\) 均为 \(m\times n\) 矩阵,则 \(A+B=C,C_{i,j}=A_{i,j}+B_{i,j}\)。
减法同理。
矩阵乘法
若有两个矩阵 \(A,B\),\(A\) 为 \(m\times p\) 矩阵,\(B\) 为 \(p\times n\) 矩阵,则 \(AB=C\),\(C\) 为 \(m\times n\) 矩阵,\(C_{i,j}=\sum_{k=1}^p A_{i,k}B_{k,j}\)。
struct matrix {long long c[101][101];long long m,n;matrix() {memset(c,0,sizeof c);}
};
matrix operator*(matrix &x,matrix &y) {//重载运算-矩阵乘法matrix t;for(int i=1;i<=x.m;i++)for(int j=1;j<=y.n;j++)for(int k=1;k<=x.n;k++)t.c[i][j]=(t.c[i][j]+x.c[i][k]*y.c[k][j])%mod;t.m=x.m,t.n=y.n;return t;
}
发现若 \(I\) 为单位矩阵,\(A\) 为与 \(I\) 同阶的方阵,则 \(AI=A\)。
矩阵快速幂
模版。
由于矩阵乘法满足结合律,所以可以使用快速幂计算一个矩阵的幂。
类似于普通快速幂。
void qpow(matrix &A,long long k) {//计算 A^kmatrix res;res.m=A.m,res.n=A.n;for(int i=1;i<=A.n;i++) res.c[i][i]=1;//构造单位矩阵辅助 while(k) {if(k&1) res=res*A;A=A*A;k>>=1;}A=res;
}
斐波那契 矩阵加速
题目传送门。
将相邻的两项 \(F_n,F_{n-1}\) 记作矩阵 \(\begin{bmatrix}F_{n}&F_{n-1}\end{bmatrix}\),现在需要通过构造一个矩阵 \(A\),使得 \(\begin{bmatrix}F_{n}&F_{n-1}\end{bmatrix}=\begin{bmatrix}F_{n-1}&F_{n-2}\end{bmatrix}\times A\)。
观察斐波那契递推公式得 \(F_n=F_{n-1}\times 1+F_{n-2}\times 1,F_{n-1}=F_{n-1}\times 1+F_{n-2}\times 0\),则矩阵 \(A=\begin{bmatrix}1&1\\1&0\end{bmatrix}\)。
故有 \(\begin{bmatrix}F_{2}&F_{1}\end{bmatrix}\times \begin{bmatrix}1&1\\1&0\end{bmatrix}^{n-2}=\begin{bmatrix}F_{2}&F_{1}\end{bmatrix}\)
A.m=A.n=2;
A.c[1][1]=A.c[1][2]=A.c[2][1]=1;
qpow(A,k-2);
F.m=F.c[1][1]=F.c[1][2]=1,F.n=2;
F=F*A;
高斯消元求解线性方程组
模版&板中板。
线性方程组
改写成矩阵
增广矩阵
将系数矩阵和常数矩阵放在一起,构成 \(n\times(n+1)\) 的增广矩阵。
矩阵的初等行变换
1.交换两行
2.将某一行乘上一个 非零的数
3.把某行的若干倍加到另一行上
(其实就是在解多元一次方程组时的消元法)
高斯消元
先看消元结果:
即若 \(i=j\),则 \(a_{i,j}'=1\);若 \(i>j\),则 \(a_{i,j}'=0\)。
步骤:
1.枚举 主元(第 \(i\) 次枚举到 \(a_{i,i}\))
2.找到最小的 \(j\) 使得 \(j\ge i\) 且 \(a_{j,i}\not=0\)
3.利用 变换1,交换第 \(i,j\) 行
4.利用 变换2,使 \(a_{i,i}\gets 1\)
5.利用 变换3,使每个 \(j>i\) 的 \(a_{j,i}\gets 0\),即使第 \(j>i\) 行减去 \(a_{j,i}\) 倍的第 \(i\) 行
之后从下到上代入即可求解。
bool gsxy() {for(int i=1;i<=n;i++) {int r=i;while(fabs(a[r][i])<eps&&r<n) r++;//找主元if(fabs(a[r][i])<eps) return 0;//报告无唯一解if(r!=i) swap(a[r],a[i]);//1for(int j=n+1;j>=i;j--) a[i][j]/=a[i][i]*1.0;//2注意一定要倒着来for(int j=i+1;j<=n;j++) {//3for(int k=n+1;k>=i;k--) a[j][k]-=a[j][i]*a[i][k]*1.0;}}for(int i=n-1;i>=1;i--) {//代入for(int j=i+1;j<=n;j++) a[i][n+1]-=a[i][j]*a[j][n+1]*1.0;}return 1;//报告有解
}
无解,无数解,唯一解
若消完 \(n\) 行,则有唯一解。
若消到第 \(i\) 行时,有 \(a_{i,i}=b_{i}=0\),则有无数组解。
若消到第 \(i\) 行时,有 \(a_{i,i}=0,b_{i}\not=0\),则无解。
高斯-约旦消元法
先看消元结果:
即若 \(i\not=j\),则 \(a_{i,j}'=0\)。
步骤:
1.枚举 主元
2.找到最小的 \(j\) 使得 \(j\ge i\) 且 \(a_{j,i}\not=0\)
3.利用 变换3,使每个 \(j\not=i\) 的 \(a_{j,i}=0\)
之后就可以得到 \(x_i=\dfrac{b_i'}{a'_{i,i}}\)。
bool gsxy() {for(int i=1;i<=n;i++) {int r=i;while(fabs(a[r][i])<eps&&r<n) r++;//找主元if(fabs(a[r][i])<eps) return 0;if(r!=i) swap(a[r],a[i]);for(int j=1;j<=n;j++) {//3if(i==j) continue;double t=a[j][i]/a[i][i];for(int k=i;k<=n+1;k++) a[j][k]-=t*a[i][k];}}for(int i=1;i<=n;i++) a[i][n+1]/=a[i][i];return 1;
}
矩阵求逆
模版。
对于方阵 \(A\),若存在同阶方阵 \(B\),使得 \(AB=BA=I\),则称 \(B\) 是 \(A\) 的逆矩阵,记为 \(A^{-1}\)。其中 \(I\) 是一个 单位矩阵。
高斯-约旦消元法求逆
构造 \(n\times 2n\) 矩阵 \((A,I)\),通过高斯-约旦消元法变为 \((I,B)\),此时 \(B\) 就是 \(A^{-1}\)。
注意:若 \((A,I)\),无法使用高斯-撒旦消元法,则矩阵 \(A\) 不可逆。
证明
看作线性方程组的形式 \(AX=I\),两边同乘 \(A^{-1}\),则有 \(IX=A^{-1},X=A^{-1}\),即消元后的 \(B=A^{-1}\)。
求模意义下的逆矩阵
1.双重模保证最小且非负
2.除法变为乘逆元,避免除法精度问题
3.逆元用费马小定理求出
bool gsxy() {for(int i=1;i<=n;i++) {int r=i;while(a[r][i]==0&&r<n) r++;if(a[r][i]==0) return 0;if(r!=i) swap(a[r],a[i]);long long x=qpow(a[i][i],mod-2);for(int j=1;j<=n;j++) {if(i==j) continue;long long t=a[j][i]*x%mod;for(int k=i;k<=2*n;k++) a[j][k]=(a[j][k]-t*a[i][k]%mod+mod)%mod;}for(int j=1;j<=2*n;j++) a[i][j]=(a[i][j]*x)%mod;}return 1;
}
排列组合
在本节中,规定 \(0!=1\)。
定义
排列
从 \(n\) 个不同元素中选取 \(m\) 个组成一种有特定顺序的 排列 的方案数为 \(A_n^m\) 或 \(A(n,m)\)。
有 \(A_n^m=\dfrac{n!}{(n-m)!}(0\le m\le n)\)。
若 \(m>n,A_n^m=0\)。
组合
从 \(n\) 个不同元素中选取 \(m\) 个形成一个 集合 的方案数为 \(C_n^m\) 或 \(C(n,m)\)。
有 \(C_n^m=\dfrac{n!}{m!(n-m)!}(0\le m\le n)\)。
若 \(m>n,C_n^m=0\)。
求组合数 递推公式
对于任意的 \(1\le m\le n\),有 \(C_n^m=C_{n-1}^m+C_{n-1}^{m-1}\)。
证明
从 \(n\) 个数中选 \(m\) 个数,
- 若第 \(n\) 个数不选,则要从 \(n-1\) 个数中选 \(m\) 个,即 \(C_{n-1}^m\)
- 若第 \(n\) 个数选,则要从 \(n-1\) 个数中选 \(m-1\) 个,即 \(C_{n-1}^{m-1}\)
杨辉三角
杨辉三角形如
即一个数等于上面两个数的和。
设其第 \(i\) 行 \(j\) 列的数为 \(a_{i,j}\),其中 \(i,j\) 从零开始,则有 \(a_{i,j}=a_{i-1,j}+a_{i-1,j-1}\),和刚刚的递推公式一模一样!所以也有 \(a_{i,j}=C_i^j\)。
时间复杂度 \(O(n^2)\)。
求模意义下的组合数
求 \(C_n^m\bmod p\),\(p\) 为质数且 \(p>n,m\)。
考虑根据 \(C_n^m=\dfrac{n!}{m!(n-m)!}(0\le m\le n)\) 直接计算 \(C_n^m\)。
记 \(f(x)\) 为 \(x!\pmod p\),\(g(x)\) 为 \((x!)^{-1}\pmod p\),由于 \(p\) 为质数且 \(p>n,m\),所以 \(m,n\) 与 \(p\) 互质,根据费马小定理就有 \(g(x)\equiv(x!)^{-1}\equiv x^{p-2}\pmod p\)。
\(f(x)\) 递推,\(g(x)\) 快速幂即可,\(C_n^m\equiv f(n)g(m)g(n-m)\pmod p\)。
时间复杂度 \(O(n\log p)\)。
void init() {f[0]=g[0]=1;for(int i=1;i<N;i++) {f[i]=(f[i-1]*i)%P;g[i]=(g[i-1]*qpow(i,P-2))%P;}
}
long long C(long long n,long long m) {return ((f[n]*g[m])%P*g[n-m])%P;
}
二项式定理
对于任意的整数 \(x,y,n\),有 \((x+y)^n=\sum_{i=0}^n C_n^ix^iy^{n-i}\)。
证明
在一个 \((x+y)\) 中,会拆出一个 \(x\) 和一个 \(y\),那么拆出 \(i\) 个 \(x\) 的情况数就为 \(C_n^i\),这些式子的和为 \(C_n^ix^iy^{n-i}\),总和即 \(\sum_{i=0}^n C_n^ix^iy^{n-i}\)。
广义二项式定理
即将二项式定理推广到实数域,即对于任意的实数 \(x,y,\alpha\),有 \((x+y)^\alpha=\sum_{i=0}^\alpha C_\alpha^ix^iy^{\alpha-i}\)。
其中 \(C_\alpha^i=\dfrac{\alpha(\alpha-1)(\alpha-2)\dots(\alpha-i+1)}{i!}\)。
卢卡斯定理
模版。
对于 质数 \(p\),且有 \(0\le m\le n\) 时,\(C_n^m\equiv C_{n/p}^{m/p}C_{n\bmod p}^{m\bmod p}\pmod p\)。
证明
引理 1:\(C_x^p\equiv 0\pmod p(0<x<p)\),\(p\) 为质数。
证明:\(C_p^x=\dfrac{p!}{x!(p-x)!}=\dfrac{p(p-1)!}{x(x-1)!(p-x)!}=\dfrac{p}{x}C_{p-1}{x-1}\),则有 \(C_p^x\equiv p\times x^{-1}\times C_{p-1}^{x-1}\equiv 0\pmod p\)。
引理2:\((1+x)^p\equiv 1+x^p\pmod p\)。
证明:由二项式定理:\((1+x)^p=\sum_{i=0}^p C_p^i x^i\),由引理 1,只剩 \(i=0\) 和 \(i=p\) 两项,即 \(1+x^p\)。
卢卡斯定理证明:
令 \(nap+b,m=cp+d\),那么有
其中 \(x^m\) 系数为 \(C_n^m\),又因为有
中 \(x^m=x^{cp+d}=x^{cp}\times x^d\) 的系数为 \(C_{a}^{c}C_{b}^{d}\),所以有 \(C_n^m\equiv C_{n/p}^{m/p}C_{n\bmod p}^{m\bmod p}\pmod p\)。
\(C_{n\bmod p}^{m\bmod p}\) 直接计算,\(C_{n/p}^{m/p}\) 递归到 \(m=0\) 即可。
时间复杂度 \(O(p\log p+\log_pn)\)。
long long C(long long n,long long m) {if(m>n) return 0;//注意特判else return ((f[n]*g[m])%P*g[n-m])%P;
}
long long lcs(long long n,long long m) {if(m==0) return 1;else return (lcs(n/P,m/P)*C(n%P,m%P))%P;
}
筛法高精度求组合数
1.筛出 \(1\sim n\) 的质数
2.计算 \(C_n^m=\dfrac{n!}{m!(n-m)!}\) 中质数 \(p\) 的个数,根据唯一分解定理,利用高精度计算答案
\(n!\) 中质因子 \(p\) 的个数 \(s=\dfrac{n}{p}+\dfrac{n}{p^2}+\dfrac{n}{p^3}+\dots\)。除法向下取整。
其实就是在求 \(1\sim n\) 中为 \(p\) 的倍数的数的个数,为 \(p^2\) 倍数的数的个数,为 \(p^3\) 倍数的数的个数……根据乘法原理,其和便为 \(n!\) 中质因子 \(p\) 的个数。
int get(int n,int p) {//n! 中 p 的个数int s=0;while(n) s+=n/p,n/=p;return s;
}
int getps(int n,int m,int p) {//C 中 p 的个数return get(n,p)-get(m,p)-get(n-m,p);
}
void mul(int p,int &len) {int t=0;for(int i=0;i<len;i++) {t+=C[i]*p;C[i]=t%10;t/=10;}while(t) {C[len++]=t%10;t/=10;}
}