欧拉函数+快速幂+扩欧+中国剩余定理
欧拉函数+快速幂+扩欧+中国剩余定理
欧拉函数
公式法
\[1-N中与N互质的数的个数被称为欧拉函数,记为\phi(N)\\
在算术基本定理中,N=P_1^{\alpha_1}P_2^{\alpha_2}...P_m^{\alpha_m},则:\\
\phi(N)=N*\frac{p_1-1}{p_1}*\frac{p_2-1}{p_2}*...*\frac{p_m-1}{p_m\\}
\]
\[1,2,3,4,5,6\\
与6互质的数有:1,5\\
6=2^1\times3^1\\
\phi(6)=6\times\frac{2-1}{2}\times\frac{3-1}{3}=2\\
\]
\[证明如下:(容斥原理)\\
1.从1-N中去除p_1,p_2,...,p_k的所有倍数\\
N-\frac{N}{p_1}-\frac{N}{p_2}-...-\frac{N}{p_k}\\
2.加上所有p_i*p_j的倍数\\
N-\frac{N}{p_1}-\frac{N}{p_2}-...-\frac{N}{p_k}+\frac{N}{p_1p_2}+\frac{N}{p_1p_3}+\frac{N}{p_{k-1}p_k}\\
3.减去所有p_i*p_j*p_k的倍数\\
N-\frac{N}{p_1}-\frac{N}{p_2}-...-\frac{N}{p_k}+\frac{N}{p_1p_2}+\frac{N}{p_1p_3}+\frac{N}{p_{k-1}p_k}-\frac{N}{p_1p_2p_3}-...-\frac{N}{p_{k-2}p_{k-1}p_{k}}\\
N-\frac{N}{p_1}-\frac{N}{p_2}-...-\frac{N}{p_k}+\frac{N}{p_1p_2}+\frac{N}{p_1p_3}+\frac{N}{p_{k-1}p_k}+...+(-1)^k\frac{N}{p_1...p_k}=N*\frac{p_1-1}{p_1}*\frac{p_2-1}{p_2}*...*\frac{p_m-1}{p_m\\}=\phi(N)\\
\]
求欧拉函数算法模板
\(O(\sqrt{n})\)
int phi(int x)
{
int res = x;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
if (x > 1) res = res / x * (x - 1);
return res;
}
筛法
求1-N每个数的欧拉函数
\[i = p_1^{\alpha_1} ...p_k^{\alpha_k}\\
primes[j] * i = primes[j]*p_1^{\alpha_1} ...p_k^{\alpha_k}\\
\\
若p为质数,那么1-p中有p-1个数和p互质\\
\\
假如i\%primes[j]==0\\
则primes[j]是i的最小质因子\\
\therefore primes[j] = p_1\\
\therefore primes[j] * i = p_1^{\alpha_1+1} ...p_k^{\alpha_k}\\
\phi(i)=i*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p_2})*...*(\frac{p_k-1}{p_k})\\
\phi(primes[j] * i)=primes[j] * i*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p_2})*...*(\frac{p_k-1}{p_k})=primes[j]*\phi(i)\\
\therefore \phi(primes[j] * i)=primes[j]*\phi(i)\\
\\
假如i\%primes[j]!=0\\
那么primes[j]一定是primes[j]*i的最小质因子,并且primes[j]不存在于i的质因子当中\\
\phi(i)=i*(\frac{p_1-1}{p_1})*(\frac{p_2-1}{p_2})*...*(\frac{p_k-1}{p_k})\\
\phi(primes[j]*i)=primes[j]*i*(\frac{p_1-1}{p_1})*...*(\frac{p_k-1}{p_k})*(\frac{primes[j]-1}{primes[j]})=primes[j]*\frac{primes[j]-1}{primes[j]}*\phi(i)\\
\therefore \phi(primes[j]*i)=(primes[j]-1)*\phi(i)\\
\]
筛法求欧拉函数算法模板
int primes[N], cnt; // primes[]存储所有素数
int euler[N]; // 存储每个数的欧拉函数
bool st[N]; // st[x]存储x是否被筛掉
void get_eulers(int n)
{
euler[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
primes[cnt ++ ] = i;
euler[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0)
{
euler[primes[j] * i] = euler[i] * primes[j];
break;
}
euler[primes[j] * i] = euler[i] * (primes[j] - 1);
}
}
}
欧拉定理
\[若a与n互质,则a^{\phi(n)} \equiv 1 (mod \; n)\\
特别地,当n为质数时,a^{n-1} \equiv 1 (mod \; n) \quad (费马定理)\\
\]
\[证明如下:\\
1-n中,与n互质的数为:a_1,a_2,...,a_{\phi(n)}\\
又\because a与n互质\\
\therefore aa_1,aa_2,...,aa_{\phi(n)}也与n互质\\
\\
已知a*a_i与n互质,要证(a*a_i)\%n与n互质\\
设c=(a*a_i)\%n\\
假设c与n不互质\\
则存在d>1,s.t.c=kd,n=jd\\
\because c=(a*a_i)\%n\\
\therefore a*a_i=fn+c=fjd+kd= (fj+k)d\\
\because n=jd\\
\therefore a*a_i与n不互质,假设不成立\\
\therefore (a*a_i)\%n与n互质\\
\\
\because (a*a_i)\%n<n\\
又\because 1-n中,与n互质的数为:a_1,a_2,...,a_{\phi(n)}\\
\therefore (a*a_i)\%n \in \{a_1,a_2,...,a_{\phi(n)}\}\\
\because (a\times b)\%n=(a\%n)\times (b\%n)且aa_1,aa_2,...,aa_{\phi(n)}互不相同\\
\therefore (aa_1\times aa_2\times ...\times aa_{\phi(n)})\%n=a_1\times a_2\times ...\times a_{\phi(n)}\\
\therefore a^{\phi(n)}\times a_1\times a_2\times ...\times a_{\phi(n)}= a_1\times a_2\times ...\times a_{\phi(n)} \; (mod \; n)\\
a^{\phi(n)} \equiv 1 (mod \; n)\\
\]
快速幂
快速求出\(a^k \; mod\; p\)
O(log k)
\[a^k \; mod\; p\\
预处理出\; a^{2^0} \; mod \; p,....,a^{2^{log\;k}}\;mod\;p这log\;k个数\\
a^k=a^{2^{x_1}}a^{2^{x_2}}...a^{2^{x_t}}=a^{2^{x_1}+2^{x_2}+...+2^{x_t}}\\
k=2^{x_1}+2^{x_2}+...+2^{x_t}\\
(101011)_2=2^0+2^1+2^3+2^5\\
\\
预处理:\\
a^{2^0}=a\\
a^{2^1}=(a^{2^0})^2\\
...\\
a^{2^{log\;k}}=(a^{2^{log\;k-1}})^2\\
每个数是前面的数的平方,预处理出log\;k个数,复杂度O(log\;k)
\]
\[(5)_{10}=(101)_2\\
4^5\;mod\;10\\
4^{2^0}\;mod\;10\equiv 4\;mod\;10\\
4^{2^1}\;mod\;10\equiv 6\;mod\;10\\
4^{2^2}\;mod\;10\equiv 6\;mod\;10\\
4^5=4^{2^0}4^{2^2}=4*6=4\;mod\;10
\]
快速幂算法模板
// 求 m^k mod p,时间复杂度 O(logk)。
int qmi(int m, int k, int p)
{
int res = 1 % p, t = m;
while (k)
{
if (k&1) res = res * t % p;
t = t * t % p;
k >>= 1;
}
return res;
}
快速幂求逆元
乘法逆元:
若整数\(b,m\)互质,并且对于任意的整数\(a\),如果满足\(b|a\),则存在一个整数\(x\),使得\(a/b\equiv a\times x\;(mod\;m)\),则称\(x\)为\(b\)的模\(m\)乘法逆元,记为 \(b^{−1}\;(mod\;m)\)。
\(b\)存在乘法逆元的充要条件是\(b\)与模数\(m\)互质。当模数\(m\)为质数时,\(b^{m−2}\)即为 b的乘法逆元。
\[\frac{a}{b}\equiv ax\;mod\;m\\
\frac{a}{b}\equiv ab^{-1}\;mod\;m\\
bx\equiv 1(mod \;p)\\
若b、p互质且p为质数,则由费马定理,有b^{p-1}\equiv1(mod\;p)\\
bb^{p-2}\equiv1(mod\;p)\\
\therefore b^{p-2}为b的乘法逆元\\
!!!充要条件:b与p互质且p为质数\\
\]
扩展欧几里得
\[裴蜀定理\\
对任意正整数a,b,一定存在非零整数x,y,使得ax+by=gcd(a,b)\\
当b=0时,ax+by=a,易得x=1,y可以取任意实数\\
当b!=0时,ax+by=gcd(a,b)=gcd(b,a\;mod\;b)\\
bx'+(a\;mod\;b)y'=gcd(b,a\;mod\;b)\\
bx'+(a-\lfloor\frac{a}{b}\rfloor b)y'=gcd(a,b)\\
ay'+b(x'-\lfloor\frac{a}{b}\rfloor y')=ax+by\\
互换x'、y'\\
ax'+b(y'-\lfloor\frac{a}{b}\rfloor x')=ax+by\\
x=x',y=y'-\lfloor\frac{a}{b}\rfloor x'\\
\\
ax+by=(a,b)\\
ax+by=d有解当且仅当d=k(a,b)\\
\]
扩展欧几里得算法模板
// 求x, y,使得ax + by = gcd(a, b)
int exgcd(int a, int b, int &x, int &y)
{
if (!b)
{
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a/b) * x;
return d;
}
求解线性同余方程
\[ax\equiv b(mod \; m)\\
ax=my+b\\
ax-my=b\\
ax+my=b\\
当b为gcd(a,m)的倍数时有解,x = (long \;long)x\times b / gcd(a,m) \% m\\
\]
中国剩余定理
\[给定一堆两两互质的数m_1,m_2,...,m_k,有线性同余方程组\\
\begin{cases}
\ x\equiv a_1(mod\;m_1) \\
\ x\equiv a_2(mod\;m_2) \\
\ ...... \\
\ x\equiv a_k(mod\;m_k) \\
\end{cases}
\\
令M=m_1m_2...m_k\\
M_i=\frac{M}{m_i}(因为m_i两两互质,所以M_i与除了m_i以外的其他m互质)\\
M_i^{-1}表示M_i模m_i的逆(用扩欧来求解)\\
M_ix\equiv1(mod\;m_i) \Rightarrow M_ix+km_i=1\\
中国剩余定理:x=a_1\times M_1\times M_1^{-1}+a_2\times M_2\times M_2^{-1} + ...+a_k\times M_k\times M_k^{-1}
\]
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 15;
ll a[N], m[N];
ll M = 1, res;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if(!b)
{
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
{
cin >> m[i] >> a[i];
M *= m[i];
}
for(int i = 1; i <= n; i ++)
{
ll Mi = M / m[i], x, k, d;
d = exgcd(Mi, m[i], x, k);
x %= m[i];
res = (res + a[i] * Mi * x) % M;
}
cout << (res % M + M) % M << endl;
return 0;
}
拓展中国剩余定理
不满足两两互质条件时
给定\(2n\)个整数\(a_1,a_2,...,a_n\)和\(m_1,m_2,...,m_n\),求一个最小的非负整数x,满足\(\forall i \in[1,n],x\equiv m_i(mod\;a_i)\)
\[\begin{cases}
\ x\equiv m_1(mod\;a_1) \\
\ x\equiv m_2(mod\;a_2) \\
\ ...... \\
\ x\equiv m_n(mod\;a_n) \\
\end{cases}
\\
\Rightarrow
\begin{cases}
\ x\;mod\;a_1=m_1 \\
\ x\;mod\;a_2=m_2 \\
\ ...... \\
\ x\;mod\;a_n=m_n \\
\end{cases}
\]
\[对于每两个式子(我们考虑将其合并):\\
\begin{cases}
\ x\;mod\;a_1=m_1\\
\ x\;mod\;a_2=m_2\\
\end{cases}
\\
\Rightarrow
\begin{cases}
\ x = k_1a_1+m_1\\
\ x = k_2a_2+m_2\\
\end{cases}
\\
\Rightarrow
k_1a_1+m_1 = k_2a_2+m_2\\
\Rightarrow k_1a_1-k_2a_2=m_2-m_1\\
\Rightarrow k_1a_1+k_2a_2=m_2-m_1\\
\because a_1、a_2、m_1、m_2已知\\
\therefore k_1a_1+k_2a_2=gcd(a_1,a_2),可求出k_1,k_2\\
k_1a_1+k_2a_2=m_2-m_1有解当且仅当gcd(a1,a2) | m2-m1\\
让k_1,k_2扩大\frac{m_2-m_1}{gcd(a_1,a_2)}倍,得到k_1a_1+k_2a_2=m_2-m_1的一组解\\
\begin{cases}
\ k1=k1+k\frac{a_2}{d}(k_1\in Z)\\
\ k2=k2+k\frac{a_a}{d}(k_2\in Z)\\
\end{cases}
\\
此时,新的k_1,k_2仍满足原式\\
但为了避免溢出,通常取k1为满足条件的最小的正整数\\
\therefore k_1=k_1\%\frac{a_2}{d},k_2=k2\%\frac{a_1}{d}\\
\therefore x=k_1a_1+m_1=(k1+k\frac{a_2}{d})a_1+m_1=a_1k_1+m_1+k\frac{a_1a_2}{d}
=a_1k_1+m_1+k*lcm(a_1,a_2)\\
令m_0=a_1k_1+m_1,a_0=lcm(a_1,a_2)\\
则x=m_0+ka_0
\]
#include <iostream>
using namespace std;
typedef long long ll;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
int main()
{
int n;
cin >> n;
ll a1, m1;
cin >> a1 >> m1;
for (int i = 0; i < n - 1; i ++ )
{
ll a2, m2, k1, k2;
cin >> a2 >> m2;
ll d = exgcd(a1, a2, k1, k2);
if ((m2 - m1) % d)
{
cout << "-1" << endl;
return 0;
}
k1 *= (m2 - m1) / d;
k1 = (k1 % (a2/d) + a2/d) % (a2/d);
m1 = k1 * a1 + m1;
a1 = a1 / d * a2;
}
ll x = (m1 % a1 + a1) % a1;
cout << x << endl;
return 0;
}