-
欧拉函数
定义:设一个数为N,求1-N中与N互质的个数ϕ(N)是多少,若在算数基本定理中,N=p1^a1*p2^a2……pk^ak,则:ϕ(N) = N*(p1 - 1)/p1 * (p2 - 1)/p2……*(pk - 1)/pk.
证明:{p1, p2 ……pk}为N的质因子,将1-N中所有质因子的倍数除去,除去的过程中可能会重复去除同一个质因子(即若p1和p2有倍数相同情况),所以要加上重复去除的质因子,在加上重复去除的质因子的操作上,可能会多加上了后面倍数更大的质因子,所以要去除多余质因子,大致过程如下:ϕ(N)=N - (N/p1 + N/p2……+N/p3)+(N/p1p2 + N/ p1p3 + N / p2p3 ……) -(N/ p1p2p3 + N / p2p3p4……)对此式子进行化简即可得到上面公式,实现代码如下
int oula(int n)
{
LL res = n;
for(int i = 2; i <= n /i; i ++)
{
if(n % i == 0)
{
res = res / i *(i - 1);
while(n % i ==0) n /= i;
}
}
if(n) res = res / n * (n - 1);
return res;
}
筛法求欧拉函数:用线性筛法求得1-n每个数的欧拉函数,线性筛法可将1-n所有的数遍历且只遍历一次,降低了时间复杂度
int parms[N], cnt;
int elur[N];
bool st[N];
void get_oula(int n)
{
for(int i = 2; i <= n; i ++)
{
if(!st[i]) parms[cnt ++] = i;
for(int j = 0; parms[j] <= n / i; j ++)
{
int t = parms[j] * i;
st[t] = true;
if(i % parms[j] == 0)
{
elur[t] = elur[i] * parms[j];
break;
}
elur[t] = elur[i] * (parms[j] - 1);
}
}
}
如果i % parms[j] == 0 说明i的质因子包含parms[j](t没有新的质因子),则t的欧拉函数有公式可知就在i的欧拉函数结果上乘以parms[j]即可,若i % parms[j] != 0 说明t有新的质因子parms[j],由公式可得elur[t] = elur[i] * (parms[j] - 1)。
-
欧拉定理
定义:gcd(a, m) = 1, 则a^ϕ(m) ≡ 1 (mod m)
证明:设1-m与m互质的数为{p1, p2, ...,pk},因为a与m互质,则{ap1, ap2...,apk}均与m互质且各不相同,由欧几里得算法可知{ap1%m, ap2%m,...apk%m}也均与m互质,若ap1%m = ap2%m 则ap1 - ap2 =0 => p1 = p2 与前面矛盾,故{ap1%m, ap2%m,...apk%m}各不相同与{p1, p2, ...,pk}一一对应,由a^ϕ(m) (p1p2..pk)%m = (p1p2..pk) 同除以(p1p2..pk)=> a^ϕ(m) ≡ 1 (mod m)
费马定理:gcd(a, m) = 1,若m为素数,a^m-1 = 1(mod m) 为欧拉定理的一种特殊情况,即m为素数