数论

来源:互联网 发布:nc.windows.app.23787 编辑:程序博客网 时间:2024/06/10 06:53

    • 逆元
      • 代码如下
      • 模版题
        • 题意
        • 题解
    • 费马小定理
      • 代码如下
    • 费马小定理推广欧拉定理
      • 求欧拉函数值代码
      • 筛出欧拉函数值的表代码

逆元

在费马小定理之前,我们先引入逆元的概念,考虑求解一个同余线性方程

axb(modm)
,要怎样求解这个方程呢,在此之前,我们先看一下求解一般的线性方程的方法,一般地,我们能将一个一元一次方程化为如下的形式:ax=b,那么在a有倒数的情况下,我们可以轻松地解出这个方程,那么同余线性方程呢?假设我们有一个方程ay1(modm),并记这个方程的解为a1,即a的逆元,那么x=a1ax=ab,即可求得方程的解.
现在的问题就变为了求解方程ay1(modm),
假设我们已经求得该方程的解,那么肯定存在整数k,使其满足以下等式:
ay=mk+1

我们将式子稍稍变形:
aymk=1

就变成了求这个式子的解!是不是看起来很眼熟?其实就是之前讲到的扩展欧几里得算法.
用扩展欧几里得算法求解这个式子后,我们就能求a的逆元啦

代码如下

int extgcd(int a,int b,int &x,int &y){    int ans=a;    if(b==0){        x=1;        y=0;    }    else{        ans=extgcd(b,a%b,y,x);        y-=a/b*x;    }    return ans;}int mod_inverse(int a,int m){    int x;    int y;    extgcd(a,m,x,y);    return (m+x%m)%m;}

模版题

http://acm.hdu.edu.cn/showproblem.php?pid=1576(HDU-1576)

题意

已知a%9973下的数n和b,a是b的倍数,且b与9973互质,求(a/b)%9973

题解

直接求带除法的取模运算是困难的,因为除法时取余与乘法,加法不同,可能改变结果,例如:

12/3%5=4
12%5/3=0.66666

因此我们考虑逆元,因为a是b的倍数,令a=bx,则bxn(mod9973),而要求的答案就是(a/b)%9973=(bx/b)%9973=x%9973,故只要求出b的逆元再乘上n即可求解
附AC代码:

#include<bits/stdc++.h>using namespace std;typedef long long int LL;const int MOD=9973;int n;int gcd(int a,int b){    if(b==0) return a;    return gcd(b,a%b);}int extgcd(int a,int b,int &x,int &y){    int ans=a;    if(b==0) {        x=1;        y=0;    }    else{        ans=extgcd(b,a%b,y,x);        y-=(a/b)*x;    }    return ans;}int mod(int b,int m){    int x,y;    extgcd(b,m,x,y);    return (m+(x*n)%m)%m;}int main(){    int T;    scanf("%d",&T);    while(T--){        LL b;        scanf("%d %lld",&n,&b);        printf("%d\n",mod(b,9973));    }   }

费马小定理

在上述背景下,我们引入费马小定理;
它的内容如下:
假设有一质数p与整数a,使得a,p互质(即gcd(a,p)=1),那么它们满足如下关系:

ap11(modp)

证明? 不会,留个坑先.
这个式子对于我们有什么好处,或者说有什么应用呢,我们对它稍稍变形:
ap2a1(modp)

其中a1就是a的逆元,利用这个定理,我们可以利用快速幂快速求解特定情况下的逆元.

代码如下

int power_mod(int x,int n,int p){    int res=1;    while(n){        if(n&1) res=(res*x)%p;        x=(x*x)%p;        n>>=1;    }    return res;}int get_mod(int a,int p){    return power_mod(a,p-2,p);}

费马小定理推广(欧拉定理)

费马小定理讨论的是p为质数的情况,对于p不是质数,我们可以将其推广至欧拉定理,其内容如下:
假设有两个整数a,n互质,那么它们有如下关系

aφ(n)1(modn)

其中φ(n)为欧拉函数,关于其的定义如下:
φ(n)=n(pi1)/pi
因为n的整数分解可以在O(n)时间内求得,因此求某一个数的欧拉函数的时间复杂度也是O(n)

求欧拉函数值代码

int eular_phi(int n){    int res=n;    for(int i=2;i*i<=n;i++){        if(n%i==0){            res=res/i*(i-1);            while(n%i==0){                n/=i;            }        }        if(n!=1) res=res/n*(n-1);        return res;     }}

筛出欧拉函数值的表代码

利用埃拉托色尼筛法,我们可以O(n)实现筛表,之后O(1)查询,代码如下:

int eular[MAXN];void eular_phi(){    for(int i=0;i<MAXN;i++){        eular[i]=i;    }    for(int i=2;i<MAXN;i++){        if(eular[i]=i){            for(int j=i;j<MAXN;j+=i){                eular[i]=eular[j]/i*(i-1);            }        }    }}
原创粉丝点击