数论专题

数论好难啊QAQ

----------------------------------------------------------------------------------

先来一些基本的数论必备代码

(1)欧拉筛

const int MAXN=3000001;
int prime[MAXN];//保存已经求出的素数
bool vis[MAXN];//判断是不是素数
int Prime(int n)
{
    int cnt=0;
    memset(vis,0,sizeof(vis)); //vis[]=0指是素数
    for(int i=2;i<n;i++)
    {
        if(!vis[i])
        prime[cnt++]=i;
        for(int j=0;j<cnt&&i*prime[j]<n;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)//欧拉筛法的精髓之处,目的是为了不重复筛除数据
            break;
        }
    }
    return cnt;//返回小于n的素数的个数
}

具体的之前博客有写:https://www.cnblogs.com/Knightero/p/12778655.html

(2)gcd与lcm

int gcd( int  a,int b)
{ return b==0?a:gcd(b,a%b); }
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}

(3)快速幂

int quick_pow(int x,int n,int mod){
    int res = 1;
    while(n > 0){
        if(n & 1)    res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
} 

------------------------------------------------------------------------------------------

新学习到的知识

(1)求逆元

运用费马小定理求逆元(其实不难)

(a/b)%mod不等于(a%mod/b%mod)%mod;

但是a/b可以看成a*b^-1

把除法转换为乘法来运算

逆元就是研究怎么已知b算出b^-1(且要有%mod,不然直接除就好了)

这时候出现了费马小定理

 

 所以要计算(a/b)%mod=(a*b^-1)%mod=(a*b^(p-2))%mod

而此刻我们会求b^(p-2),利用快速幂可求

long long int quick_pow(long long int a, long long int b)
{

    long long int ans = 1;
    while (b) {
        if (b & 1) ans = (ans * a) % mod;
        b >>= 1;
        a = (a * a) % mod;
    }
    return ans;
}
long long int inv(long long int a, long long int b)//求(a/b)%mod
{
    return a * quick_pow(b, mod - 2) % mod;
}

 (2)欧拉函数

学习视频:https://www.bilibili.com/video/BV1p741117w4?from=search&seid=17822651721941687634

欧拉函数就是给定一个n,求小于等于n中与n互质的数有几个

int Euler(int n)
{
    int res = n;
    for (int i = 2; i <= n; i++)
    {
        if (n == 1)break;
        if (n % i == 0)
        {
            res = res / i * (i - 1);//这步在视频9:15处
        }
        while (n % i == 0) n /= i;
    }
    return res;
}

 (3)欧拉函数打表

利用公式

 

 先给全体phi【】附上i的值,起到了公式中n的作用,然后 i == phi[i],说明是质数(为什么是质数往后看)

确定是质数之后,遍历质数的倍数,因为质数的倍数根据唯一分解定理肯定会含有此质数

然后对这个倍数利用公式修改其phi值

void EulerMeter() {
    for (int i = 1; i < N; i++)
        phi[i] = i;
    for (int i = 2; i < N; i++)
    {
        if (i == phi[i])
        {
            for (int j = i; j < N; j += i)
            phi[j] = phi[j] / i * (i - 1);
        }
    }
}

 

posted @ 2020-07-16 11:09  dorayaki桑  阅读(181)  评论(0编辑  收藏  举报
//自动生成目录 levels of contents