欧拉定理&&费马小定理

欧拉定理

在这里插入图片描述

下面为欧拉定理的扩展
在这里插入图片描述

欧拉定理可进行欧拉降幂:
若gcd(a,p)=1;
a ^ b mod p = a ^ ( b % phi§ + phi§ ) (mod p)
由于欧拉函数很快就能降为1,所以递归几次即可快速得出答案。
可做这题https://cn.vjudge.net/problem/14888/origin
ac代码

#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;

long long pow_mod(long long a,long long b,long long m){
    if(b==0) return 1;
    long long x=pow_mod(a,b>>1,m);
    long long ans=x*x%m;
    if(b%2) ans=ans*a%m;
    return ans;
}

long long phi(long long n){
    long long m=sqrt(n+0.5);
    long long ans=n;
    for(int i=2;i<=m;i++){
        if(n%i==0){
            ans=ans/i*(i-1);
            while(n%i==0) n/=i;
        }
    }
    if(n>1) ans=ans/n*(n-1);
    return ans;
}


long long solve(long long a,long long b){
    if(b==1) return 0;
    long long d=phi(b);
    return pow_mod(a,d+solve(a,d),b);
}


int main(){
    int p,m,f=1;
    while(scanf("%d%d",&p,&m)!=EOF){
        long long x=1;
        for(int i=2;i<=m;i++) x*=i;
        long long ans=solve(p,x);
        if(f) f=0;
        else printf("\n");
        printf("%lld\n",ans);
    }
    return 0;
}

欧拉函数

n的欧拉函数值phi(n)为1到n的与n互质的数的个数。

欧拉函数的性质

①:如果n为某一个素数p,则φ§=p-1;
②:如果n为某一个素数p的幂次,那么φ(pa)=(p-1)*p(a-1);
③:如果n为任意两个数a和b的积,那么φ(ab)=φ(a)φ(b);
④:设n=(p1 ^ a1 ) * (p2 ^ a2 )
……
(pk ^ ak) (为N的分解式)
那么φ(n)=n * (1-1/p1) * (1-1/p2) * ……*(1-1/pk)

求单个值的欧拉函数

复杂度O(sqrt(n))

 int euler_Phi(int n){
      int m=(int)sqrt(n+0.5);
      int ans=n;
      for(int i=2;i<=m;i++){
         if(n%i==0){
              ans=ans/i*(i-1);
              while(n%i==0) n/=i;
          }
     }
     if(n>1) ans=ans/n*(n-1);
     return ans;
 }

求1~n各个数的欧拉函数

复杂度O(nloglogn)

void get_Phi(){
     for(int i=2;i<=N;i++) Phi[i]=0;
     Phi[1]=1;
     for(int i=2;i<=N;i++){
         if(!Phi[i]){
             for(int j=i;j<=N;j+=i){
                 if(!Phi[j]) Phi[j]=j;
                Phi[j]=Phi[j]/i*(i-1);
             }
        }
     }
 }

复杂度0(n)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int prime[100001],mark[1000001];//prime是素数数组,mark为标记不是素数的数组
int tot,phi[100001];//phi为φ(),tot为1~i现求出的素数个数
void getphi(int N){
    phi[1]=1;//φ(1)=1
    for(int i=2;i<=N;i++){//从2枚举到N
        if(!mark[i]){//如果是素数
            prime[++tot]=i;//那么进素数数组,指针加1
            phi[i]=i-1;//根据性质1所得
        }
        for(int j=1;j<=tot;j++){//从现求出素数枚举
            if(i*prime[j]>N) break;//如果超出了所求范围就没有意义了
            mark[i*prime[j]]=1;//标记i*prime[j]不是素数
            if(i%prime[j]==0){//应用性质2
                phi[i*prime[j]]=phi[i]*prime[j];break;
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];//应用性质3
        }
    }
}
int N;
int main(){
    cin>>N;
    getphi(N);
    for(int i=1;i<=N;i++){
        cout<<i<<":phi ( "<<phi[i]<<" )"<<endl;//输出phi(i)
    }
}

代码来自https://blog.csdn.net/update7/article/details/70943545

费马小定理

若gcd(a,p)=1;
则 a^(p-1) ≡ 1(mod p)

费马小定理的应用

①判断大素数:多次设置a的值带入a^(p-1) mod p,若结果都为1,则可大致判断p为素数。(Miller-Rabin 素数判定)
②求解逆元:设a mod p的逆元为 x,则可知x=a ^ (p-1)
③简化模计算:对于素数p,任取跟他互素的数a,有a ^ (p-1) (mod p) =1 所以任取b,有a ^ b%p=a ^ (b%(p-1)) (%p)从而简化运算。通常结合快速幂

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页