数论基础

本文介绍了数论的基础概念,包括欧几里德算法求最大公因子,扩展欧几里德算法求解线性同余方程,线性筛素数方法,唯一分解定理,欧拉函数的计算,以及如何求乘法逆元,详细讨论了费马小定理和三种求逆元的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欧几里德算法

即求两个数的最大公因子

int GCD(int a,int b)
{
    if(b == 0) return a;
    else return GCD(b,a % b);
}

扩展欧几里德算法

它可以用来求解ax + by = c(a,b,c为整数)的方程的一组整数解,事实上,只有GCD(a,b) | c时,此方程才有整数解。具体实现

这里写图片描述

ll exgcd(ll a,ll b,ll& x,ll& y)
{
    ll d = a;
    if(b != 0) {
        d = exgcd(b,a % b,y,x);
        y -= (a / b) * x;
    }
    else {
        x = 1,y = 0;
    }
    return d;
}

根据扩展欧几里德求ax+by=c的最小正整数解,先得到ax + by = gcd(a,b)的解(x0,y0),如果c能整除gcd(a,b)则表明该方程有解,x1 = (x0 * c / (gcd(a,b)),最小正整数解为(x1 % (b / gcd(a,b) + b / gcd(a,b)) % (b / gcd(a,b))。

线性筛素数

时间复杂度O(n)

#include <stdio.h>
#include <string.h>
#define maxn 100005
bool isPrime[maxn];
int prime[maxn];
void init()
{
    int i,j,cnt;
    cnt = 0;
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0] = isPrime[1] = false;
    for(i = 2; i < maxn; i++) {
        if(isPrime[i])
            prime[cnt++] = i;
        for(j = 0; j < cnt && i * prime[j] < maxn; j++) {
            isPrime[i * prime[j]] = false;
            if(i % prime[j] == 0)
                break;
        }
    }
}
int main(void)
{
    init();
    return 0;
}

 

唯一分解定理

每一个数都可以表示为p1^{a1} * p2^{a2} * p3^{a3} *......*pn^{an}p1,p2......pn都是素数,由此可以得出一个数的因子数为(a1 + 1) * (a2 + 1) * (a3 + 1) * ...... * (an + 1)

#include <bits/stdc++.h>
using namespace std;
map<int,int> prime_factor(int n)
{
    int i;
    map<int,int> res;
    for(i = 2; i * i <= n; i++) {
        while(n % i == 0) {
            res[i]++;
            n /= i;
        }
    }
    if(n != 1)
        res[n] = 1;
    return res;
}
int main(void)
{
    map<int,int> res = prime_factor(130);
    map<int,int>::iterator it;
    for(it = res.begin(); it != res.end(); it++) {
        printf("%d %d\n",it -> first,it -> second);
    }
    return 0;
}

欧拉函数

对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目\varphi (1) = 1,互质即a,b,b两个数的公因子只有1。

下面代码即筛出来了素数,也求出了欧拉。

#include <stdio.h>
#include <string.h>
const int maxn = 10000000;
bool isPrime[maxn + 10];
int phi[maxn + 10];
int prime[maxn + 10];
int tot;
void init(int N)
{
    int i,j;
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0] = isPrime[1] = false;
    tot = 0;
    phi[1] = 1;
    for(i = 2; i <= N; i++) {
        if(isPrime[i]) {
            prime[tot++] = i;
            phi[i] = i - 1;
        }
        for(j = 0; j < tot; j++) {
            if(i * prime[j] > N)
                break;
            isPrime[i * prime[j]] = false;
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            else
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}
int main(void)
{
    int i;
    init(105);
    for(i = 0; i <= 105; i++)
        printf("%d %d\n",i,phi[i]);
    return 0;
}

求单个数的欧拉

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

乘法逆元

如果ax\equiv 1 (mod p),且gcd\left (a, \right p ) = 1,则称a关于模p的乘法逆元为x

\left (a \right / b) mod p = a \ast a^{-1} mod pa^{-1}关于模p的乘法逆元

求逆元三种方法

费马小定理

若p为素数,则有a^{p-1}\equiv 1(modp) 
a^{p-2}*a\equiv 1(modp)
a{^{p-2}}就是a在mod p意义下的逆元

代码用快速幂实现

ll q_pow(ll a,ll b,ll mod)
{
    ll res,base;
    res = 1;
    base = a;
    while(b) {
        if(b & 1)
            res = (res * base) % mod;
        base = (base * base) % mod;
        b >>= 1;
    }
    return res;
}
ll getInv(ll a,ll mod)
{
    return q_pow(a,mod - 2,mod);
}

用扩展欧几里德求乘法逆元:

ax\equiv 1 (mod p)

ax + kp = 1

代码实现

ll exgcd(ll a,ll b,ll& x,ll& y)
{
    ll d = a;
    if(b != 0) {
        d = exgcd(b,a % b,y,x);
        y -= (a / b) * x;
    }
    else {
        x = 1,y = 0;
    }
    return d;
}
ll getInv(ll a,ll mod)
{
    ll x,y;
    ll d = exgcd(a,mod,x,y);
    return d == 1 ? (x % mod + mod) % mod : -1;
}

递推求逆元

应用于求组合数


LL fac[MAXN],facinv[MAXN];
LL qpow(LL a, LL b)
{
    LL res = 1;
    while(b) {
        if(b & 1) res = (res * a) % MOD;
        a = (a * a) % MOD;
        b >>= 1;
    }
    return res;
}
void init()
{
    fac[0] = 1;
    for(int i = 1; i < MAXN; i++)
        fac[i] = fac[i - 1] * i % MOD;
    facinv[MAXN - 1] = qpow(fac[MAXN - 1], MOD - 2);
    for(int i = MAXN - 1; i > 0; i--)
        facinv[i - 1] = facinv[i] * i % MOD;
}
LL C(LL n, LL m)
{
    if(n < 0 || m < 0 || m > n)
        return 0;
    return fac[n] * facinv[m] % MOD * facinv[n - m] % MOD;

}

 

数论基础及其应用 作者:沈忠华 编著 出版时间:2015年版 内容简介   《数论基础及其应用》为数学与密码学交叉学科的特色教材,内容包括整除理论、同余、连分数、同余方程、原根。《数论基础及其应用》以数论知识为主线,有机地融入数论应用(主要是在密码学中的应用)的内容,理论与应用的知识的广度和深度都适度。《数论基础及其应用》可作为数学与应用数学专业、信息与计算科学专业和信息安全专业的本科生基础教材,也可作为密码学与信息安全专业的研究生教材。 目录 前言 第1章整除理论 1.1带余数除法 1.2辗转相除法 1.3最大公约数的性质 1.4最小公倍数 1.5算术基本定理 第2章同余 2.1同余的基本性质 2.2计算星期几 2.3循环比赛 第3章简单密码 3.1仿射加密 3.2矩阵加密 第4章剩余系 4.1完全剩余系 4.2简化剩余系 4.3Euler定理,Fermat定理 4.4数论函数 第5章不定方程 5.1一次不定方程 5.2方程x2+y2=x2 第6章同余方程 6.1同余方程的基本概念 6.2孙子定理 6.3模ρα的同余方程 6.4素数模的同余方程 第7章公钥密码 7.1公钥密码系统 7.2RSA加密 第8章二次剩余 8.1素数模的二次同余方程 8.2Legendre符号,二次互反律 8.3Jacobi符号 第9章原根 9.1指数及其基本性质 9.2原根与指标 9.3伪素数 第10章实数的表示 10.1连分数的基本性质 10.2实数的连分数表示 10.3循环连分数 10.4实数的b进制表示 第11章平方和 11.1二平方之和 11.2四平方之和 附录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值