首页 > 其他分享 >数论

数论

时间:2024-11-24 18:43:59浏览次数:3  
标签:return 数论 res ll cin int include

目录

数论

一、质数

1)试除法判断质数

bool isPrime(int x)
{
    if(x < 2) return false;
    for(int i = 2;i<=x/i;i++)
        if(x%i==0) return false;
    return true;
}

2)分解质因数

void divide(int n)
{
    for (int i = 2; i <= n / i; i ++ )
    {
        if( n % i == 0 )
        {
            int s = 0;
            while (n % i == 0)
            {
                n /= i;
                s++;
            }
            printf("%d %d\n",i,s);
        }
    }
    if (n > 1) printf("%d %d\n",n,1);
    puts("");
}

3)筛质数

1、普通筛质数

void getPrimes(int n)
{
    for (int i = 2; i <= n; i ++)
    {
        if (!st[i])
        {
            primes[cnt ++] = i;
        }
        for (int j = i + i; j <= n; j ++) st[j] = true;
    }
}

2、埃氏筛质数

void getPrimes(int n)
{
    for (int i = 2; i <= n; i ++)
    {
        if (!st[i])
        {
            primes[cnt ++] = i;
            for (int j = i + i; j <= n; j ++) st[j] = true;  //只对质数的倍数筛掉
        }
    }
}

3、欧拉筛

void getPrimes(int n)
{
    for (int i = 2; i <= n; i ++)
    {
        if(!st[i]) primes[cnt ++] = i;
        for (int j = 0; primes[j] <= n / i; j ++)
        {
         	st[primes[j] * i] = true;  //每次把对应的倍数筛掉
            if (i % primes[j] == 0) break;  //primes[j]是i的最小质因子,我们只用最小质因子来筛,所以遇到了就break
        }
    }
}

二、约数

1)试除法求约数

#include <bits/stdc++.h>
using namespace std;
int n;
vector<int> gcd(int n)
{
    vector<int> res;
    for(int i = 1; i <= n / i; i ++)
    {
        if(n % i == 0)
        {
            res.push_back(i);
            if (i != n / i) res.push_back(n / i);
        }
    }
    sort(res.begin(),res.end());
    return res;
}

int main()
{
    scanf("%d", &n);
    while (n --)
    {
        int x;
        scanf("%d", &x);
        auto res = gcd(x);
        for(auto item:res) printf("%d ", item);
        puts("");
    }
    return 0;
}

2)求n个数的积对常数取模的结果

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e9+7;
int n;
int main()
{
    cin >> n;
    ll res = 1;
    unordered_map<int,int> primes;
    while (n --)
    {
        int x;
        cin >> x;
        for (int i = 2; i <= x / i; i ++)
        {
            while (x % i == 0)
            {
                x /= i;
                primes[i] ++ ;
            }
        }
        if(x > 1) primes[x] ++ ;
    }
    //至此,我们就把最后的乘积的每个质因子的指数都求出来了,根据公式得出约数个数是(a1+1)*(a2+1)……*(ak+1);
    for (auto item : primes) res = res * (item.second + 1) % N;
    printf("%lld", res);
    return 0;
}

3)求n个数的积的约数个数

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod = 1e9 +7;
int n;
int main()
{
    cin>>n;
    unordered_map<int,int> primes;
    while (n -- )
    {
        int x;
        cin>>x;
        for(int i = 2;i<=x/i;i++)
            while(x%i==0)
            {
                x/=i;
                primes[i]++;
            }
        if(x>1) primes[x]++;
    }
    ll res = 1;
    for(auto prime:primes)
    {
        int p = prime.first, a = prime.second;
        ll t = 1;
        while (a -- ) t = (t * p + 1) % mod;
        res = res * t % mod;
    }
    cout<<res;
    return 0;
}

4)求最大公约数

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

三、欧拉函数

欧拉函数的证明

1)欧拉函数

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n --)
    {
        int a;
        cin >> a;
        int res = a; // res存储最终的结果
        for (int i = 2; i <= a / i; i ++) // 对数据先进行质因数分解
        {
            if(a % i == 0) // i是a的一个约数
            {
                res = res / i * (i - 1); // 化简之后的,相当于乘以 1-(1/i) 
                while (a % i == 0) a /= i;
            }
        }
        if(a > 1) res = res / a * (a - 1);
        cout << res <<endl;
    }
    return 0;
}

2)筛法求欧拉函数

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
int primes[N],cnt;
ll phi[N]; // 欧拉函数
bool st[N]; // 标记是否是质数
ll get_Olers(int n)
{
    phi[1] = 1;
    for (int i = 2; i <= n; i ++ )
    {
        if(!st[i])
        {
            primes[cnt ++ ] = i;
            phi[i] = i-1; // i是质数,1~i-1都与它互质
        }
        for(int j = 0; primes[j] <= n / i; j ++)
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0)
            {
                phi[primes[j] * i] = phi[i] * primes[j];
                break;
            }
  //如果primes[j]不是i的质因子,那么phi[primes[j]*i] = phi[i] * primes[j] * (1-1/primes[j]),化简得到如下代码
            phi[primes[j] * i] = phi[i] * (primes[j] - 1);
        }
    }
    ll res = 0;
    for(int i = 1; i <= n; i ++) res += phi[i];
    return res;
}
int main()
{
    int n;
    cin >> n;
    cout << get_Olers(n) << endl;
    return 0;
}

四、快速幂

欧拉定理

快速幂

#include <iostream>
using namespace std;
typedef long long ll;
ll qmi(ll a, ll k, ll p)
{
    ll res = 1;
    while (k)
    {
        if (k & 1) res = res * a % p;
        k = k >> 1;
        a = a * a % p;
    }
    return res;
}
int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        ll a,k,p;
        scanf("%lld%lld%lld",&a,&k,&p);
        printf("%lld\n",qmi(a,k,p));
    }
    return 0;
}

快速幂求逆元

#include <iostream>
using namespace std;
typedef long long ll;
ll qmi(ll a, ll k, ll p)
{
    ll res = 1;
    while (k)
    {
        if (k & 1) res = res * a % p;
        k = k >> 1;
        a = a * a % p;
    }
    return res;
}
int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        ll a,p;
        scanf("%lld%lld",&a,&p);
        ll res = qmi(a,p-2,p);
        if (a % p) printf("%lld\n",res);
        else puts("impossible");
    }
    return 0;
}

五、扩展欧几里得算法

裴属定理

扩展欧几里得算法(求ax + by = gcd(a,b) 中的x和y的算法)

#include <iostream>
using namespace std;
int exgcd(int a, int b, int &x, int &y)
{
    if(!b)
    {
        x = 1,y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}
int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        int a,b,x,y;
        scanf("%d%d",&a, &b);
        exgcd(a,b,x,y);
        printf("%d %d\n",x,y);
    }
    return 0;
}

线性同余方程(求 ax % m = b 式子中的x,给定a,b,m)

#include <iostream>
using namespace std;
typedef long long ll;
int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x = 1, y = 0;
        return a;
    }
    
    int d = exgcd(b,a%b,y,x);
    y -= a/b*x;
    return d;
}
int main()
{
    int n;
    cin >> n;
    while (n -- )
    {
        int a,b,m;
        scanf("%d%d%d",&a,&b,&m);
        int x,y;
        int d = exgcd(a,m,x,y);
        if (b % d) puts("impossible");
        else printf("%d\n",(ll)x * b / d % m);
    }
    return 0;
}

六、中国剩余定理

F72009F791B0CF9C9CC369CEAB2A2B85.jpg

题目:

给定 2n2

标签:return,数论,res,ll,cin,int,include
From: https://www.cnblogs.com/zj-cnbolgs/p/18566153

相关文章

  • Python数论应用
    引言        在前面的课程中,我们已经学习了Python的基本输入输出、数据类型及其转换、顺序结构、分支结构、循环结构、循环控制语句、字符串类型、列表类型、元组类型、字典类型、集合类型、函数的定义与使用、函数调用与作用域、函数的高级应用、质数、倍数与余数......
  • 数论学习笔记(一)(2024.7.25)
    一、最大公约数定义不全为\(0\)的整数\(a,b\)的最大公约数是指能够同时整除\(a\)和\(b\)的最大整数。欧几里得算法(gcd)gcd是用来求解两个整数的最大公约数定理1.2.1对于整数\(a,b,m,n\),若\(c\mida,c\midb\),则\(c\mid(ma+nb)\)证:\(\becausec\mida......
  • 数论 莫比乌斯反演
    前置需求数论分块概念对于一个形如\(\sum_{x=1}^n\lfloor{\frac{n}{x}}\rfloor\)的式子,我们发现对于一部分的\(x\),它们的\(\lfloor{\frac{n}{x}}\rfloor\)值相同,因此我们没必要\(\mathcal{O(n)}\)计算,可以采用数论分块的办法将这一步的复杂度降低至\(\mathcal{O(\sqrt......
  • 数论
    1.欧拉函数我们定义\(\varphi(n)=\sum^n_{i=1}[\gcd(i,n)==1]\)。特殊的当\(n\)为质数的时候,\(\varphi(n)=n-1\)。假如我们定义\(n=p_1^{a_1}\timesp_2^{a_2}\times\cdots\cdots\timesp_k^{a_k}\),那么\(\varphi(n)=n\times\dfrac{p_1-1}{p_1}\t......
  • Luogu P11036 GCD 与 LCM 问题 [ 蓝 ] [ 构造 ] [ 数论 ] [ adhoc ]
    LuoguP11036GCD与LCM问题:梦熊的题真是又神又逆天。思路观察到有个奇数的特殊性质,我们尝试从奇数构造入手。先来尝试带入极端数据,对于\(\gcd\),我们可以把\(b=1\)的情况先带进去看看。\[a+b+c+d=\gcd(a,b)+\operatorname{lcm}(c,d)\]\[a+1+c+d=1+\operatorname{lcm}(c,......
  • 学习笔记:数论分块
    数论分块1.0可以快速计算一些含有除法向下取整的和式(形如$\sum_{i=1}^ng(i)\left\lfloor\frac{n}{i}\right\rfloor$)。2.0引理1:\(\left\lfloor\frac{n}{i}\right\rfloor\)的取值最多只有\(2\times\sqrtn\)种。证明:对于\(i\le\left\lfloor\sqrtn\rig......
  • 数论四大定理——裴蜀定理
    好久不见,开学和假期天天搞csp实在没时间搞CSDN,终于抽出一点时间来写会文章了。我们先来看一道NOIP提高组的题目题目描述小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。每种金币小凯都有无数个。在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。现在......
  • 数论分块扩展
    【OI-wiki#5805】feat(math/number-theory/sqrt-decomposition.md):增加数论分块的拓展&改动部分格式以计算含有\(\left\lfloor\sqrt{\frac{n}{d}}\right\rfloor\)的和式为例。考虑对于一个正整数\(n\),如何求出集合\[S=\left\{\left\lfloor\sqrt{\frac{n}{d}}\right\rf......
  • 数论基础
    数论基础数论函数数论函数是指这样一类函数:其定义域是正整数,值域是一个数集。定义两个数论函数的加法,为逐项相加,即\((f+g)(n)=f(n)+g(n)\)。定义数乘这个数和每一项都相乘,即\((xf)(n)=x\timesf(n)\)。常见数论函数\[1(x)=1\\\epsilon(x)=[x=1]\\id(......
  • 部分数论函数结论的证明
    从莫比乌斯反演的文章里迁移出来的。部分数论函数结论的证明前面的小节中,我们使用了一些数论函数相关的结论,但并未给出证明。接下来我们来证明它们。欧拉函数证明\[\varphi(ij)=\dfrac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\]由欧拉函数公式,设\(x......