扩大
缩小

费马小定理和欧拉定理

费马小定理和欧拉定理

1.费马小定理

1)定义

我们现在设正整数\(a,m\)\(m\)是素数
我们就会有式子

\[a^{m-1}\equiv1(mod\ m) \]

2)证明

我们设一个完全剩余系\(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) \]

2.欧拉定理

1)欧拉函数

欧拉函数记为\(\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] \]

欧拉函数是积性函数,由它的意义我们可以用乘法原理证明,同时显然可以知道这不是完全积性函数

例如三个正整数10,2,5,我们可以算到\(\phi(10)=4\)

\((n,m)=1\),则有

\[\phi(nm)=\phi(n)*\phi(m) \]

我们可以根据定义得到如果n为素数,则\(\phi(n)=n-1\),这个东西反向也是成立的
我们可以根据这些性质来写出欧拉函数的线性筛法
代码如下:

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)\)时计算速度会快很多

欧拉心算

给出一个正整数\(n(n<=10^7)\),求

\[\sum_{i=1}^{n}\sum_{j=1}^{n}\phi({gcd(i,j)}) \]

思路:

显然我们暴力是过不了的我们要考虑\(O(n)\)或者更高效的算法

我们肯定要推式子,所以直接拿那个题目的式子来推

其中

\[sum(n)=\sum_{i=1}^{n}\phi(i) \]

img

这样我们就可以推出原式为

\[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;
}

2)定义

现在我们来引入欧拉定理,实际上欧拉定理就是费马小定理的推广在m为素数时显然就是费马小定理
我们先定义两个互质的正整数\(a,m\)
我们就会有

\[a^{\phi(m)}\equiv1(mod \ m) \]

3)证明

我们令\(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) \]

posted @ 2018-09-12 13:52  ezoiHY  阅读(665)  评论(0编辑  收藏  举报