费马小定理和欧拉定理ios
咱们如今设正整数$a,m$且$m$是素数 咱们就会有式子 $$a^{m-1}\equiv1(mod\ m)$$算法
咱们设一个彻底剩余系$A={1,2,3,...,m-1}$ 又由于$(a,m)=1$ 咱们又获得另外一个彻底剩余系$B={1a,2a,3a,...,(m-1)a}$,这里其实就是一个余数的可乘性的运用 根据彻底剩余系的性质咱们 $$(m-1)!\equiv(m-1)!*a^{m-1}(mod\ m)$$ 两边同时消去就可得 $$a^{m-1}\equiv1(mod\ m)$$函数
欧拉函数记为$\phi$,且一般定义在正整数域上 比较直接点,欧拉函数通式是长这样的 $$\phi(n)=n\prod^{x}{i=1}(1-\frac{1}{p_i})$$ 其中x为n的质因数个数,而$p_i$是n的第i个质因数 其实欧拉函数更重要的意义是:$\phi(n)$表示小于等于n且与n互质的正整数的个数 由此咱们能够的这么一条伪通式 $$\phi(n)=\sum^{n}{i=1}[(n,i)==1]$$ 欧拉函数是积性函数,由它的意义咱们能够用乘法原理证实,同时显然能够知道这不是彻底积性函数ui
例如三个正整数10,2,5,咱们能够算到$\phi(10)=4$spa
若$(n,m)=1$,则有 $$\phi(nm)=\phi(n)*\phi(m)$$ 咱们能够根据定义获得若是n为素数,则$\phi(n)=n-1$,这个东西反向也是成立的 咱们能够根据这些性质来写出欧拉函数的线性筛法 代码以下:code
void getEuler(int x){ eul[1]=1; for(int i=2;i<=x;i++){ if(!eul[i]){ pri[++tot]=i; eul[i]=i-1; } for(int j=1;j<=tot and i*pri[j]<=x;j++){ if(!(i%pri[j])){ eul[i*pri[j]]=eul[i]*pri[j]; break; } eul[i*pri[j]]=eul[i]*(pri[j]-1); } } }
欧拉函数在信息学竞赛中使用的仍是蛮多的,固然在解决实际数学问题中欧拉函数也是一个极其有用的东西,例如咱们在求${17}^{2017}\equiv x(mod\ 23)$时计算速度会快不少blog
给出一个正整数$n(n<=10^7)$,求 $$\sum_{i=1}^{n}\sum_{j=1}^{n}\phi({gcd(i,j)})$$get
显然咱们暴力是过不了的咱们要考虑$O(n)$或者更高效的算法数学
咱们确定要推式子,因此直接拿那个题目的式子来推string
其中
$$sum(n)=\sum_{i=1}^{n}\phi(i)$$
这样咱们就能够推出原式为
$$2*\sum^n_{d=1}{(\phi(d)*sum(\lfloor \frac{n}{d} \rfloor))}-sum(n)$$
因此咱们能够用线性筛筛出欧拉函数而后咱们再求一次前缀和
代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int tot,n,pri[10000001]; long long eul[10000001]; inline int rd(){ register int x=0,y=1;register char c=getchar(); while(c<'0' or c>'9'){ if(c=='-')y=-1; c=getchar(); } while(c>='0' and c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*y; } void getEuler(int x){ eul[1]=1; for(int i=2;i<=x;i++){ if(!eul[i]){ pri[++tot]=i; eul[i]=i-1; } for(int j=1;j<=tot and i*pri[j]<=x;j++){ if(!(i%pri[j])){ eul[i*pri[j]]=eul[i]*pri[j]; break; } eul[i*pri[j]]=eul[i]*(pri[j]-1); } } for(int i=2;i<=x;i++)eul[i]+=eul[i-1]; } long long solve(int x){ long long ret=0;int nxt; for(int i=1;i<=x;i=nxt+1){ nxt=x/(x/i); ret+=(eul[nxt]-eul[i-1])*eul[x/i]*2-(eul[nxt]-eul[i-1]); } return ret; } int main(){ n=rd(); getEuler(10000000); while(n--){ int x=rd(); printf("%lld\n",solve(x)); } return 0; }
如今咱们来引入欧拉定理,实际上欧拉定理就是费马小定理的推广在m为素数时显然就是费马小定理 咱们先定义两个互质的正整数$a,m$ 咱们就会有 $$a^{\phi(m)}\equiv1(mod \ m)$$
咱们令$r=\phi(n)$ 咱们先设一个有$r$个元素的集合$P={p_1,p_2,p_3,...p_r}$,其中$p_i$是第i个与m互质的数 又由于$(a,m)=1$,且P集合中的全部元素都与m互质,因此集合$P'={ap_1,ap_2,ap_3,...ap_r}$的全部元素都与m互质,且属于模m的r个不一样的剩余类$[p_1],[p_2],..[p_r]$,这里咱们用同余的性质很容易就能够想到 $$a^r*\prod_{i=1}^{r}{p_i}\equiv\prod_{i=1}^{r}{p_i}(mod \ m)$$ 消去可得 $$a^r\equiv1(mod\ m)$$ 因此 $$a^{\phi(m)}\equiv1(mod\ m)$$