数论学习记录

数论

前言:这是一篇个人学习过程的记录,文章供正在学习大家一起分享,如有不完整,不正确的地方,欢迎留言补充指正。

欧几里得算法(裴蜀定理 - OI Wiki

介绍:这个定理是一个关于最大公约数的定理,用于快速求解两数的最大公约数。

代码

int gcd(int a, int b)  // 欧几里得算法
{
    return b ? gcd(b, a % b) : a;
}

拓展

扩展欧几里得算法:此算法的原理与线性同余方程 - OI Wiki是相同的看这一篇就行了。

代码

int exgcd(int a, int b, int &x, int &y)  // 扩展欧几里得算法, 求x, y,使得ax + by = gcd(a, b)
{
    if (!b)
    {
        x = 1; y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= (a / b) * x;
    return d;
}

最小公倍数:这是与最大公约数相对应的概念,与其相关的定理是“ab最大公约数最小公倍数乘积等于ab乘积”。

约数定理(约数个数定理,约数和定理):用来求解约数个数和约数和的定理。定理的说明在链接里非常详细,在具体执行代码的过程中,还需要用到分解质因数。代码链接:分解质因数_百度百科 (baidu.com)

//约数个数定理
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 2050;// n以内的质数
bool st[N];
int cnt = 0,prime[N];

void get_primes(){
    for(int i = 2; i <= 2020; i++)
    {
        if(!st[i])                         
            prime[cnt++] = i;

        for(int j = 0; prime[j] <= 2020 / i; j++)  
        {
            st[prime[j] * i] = true;
            if(i % prime[j] == 0)               
                break;
        }
    }
}//筛质数
int factor_count(int n){ 
    int ans = 1,sum;
    for(int i = 0; prime[i] < n / prime[i]; i++){  
        if(n % prime[i] == 0){  
            sum = 0;  
            while(n % prime[i] == 0){  
                sum++;  
                n /= prime[i];  
            }  
            ans *= (sum+1);
        }  
    }
	  
    if(n > 1)  
        ans *= 2;  
    return ans; 
}  

int main()
{
  int n;
  get_primes();
  cin >> n;
  cout <<factor_count(n); 
  return 0;
}
//约数和定理
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 2050;// n以内的质数
bool st[N];
int cnt = 0,prime[N],MOD = 1000000;//要%的数

void get_primes(){
    for(int i = 2; i <= 2020; i++)
    {
        if(!st[i])                         
            prime[cnt++] = i;

        for(int j = 0; prime[j] <= 2020 / i; j++)  
        {
            st[prime[j] * i] = true;
            if(i % prime[j] == 0)               
                break;
        }
    }
}//筛质数
int pow_mod(int a,int n,int MOD){
    int ans = 1;
    while(n){
        if(n&1)
            ans = (ans*a)%MOD;
        n >>= 1;
        a = (a*a)%MOD;
    }
    return ans;
}
 
int factor_sum(int n){
    int ans = 1,sum;
    for(int i = 0; prime[i] < n / prime[i]; i++){
        if(n % prime[i] == 0){
            sum = 0;
            while(n%prime[i] == 0){
                sum++;
                n /= prime[i];
            }
            ans *= (pow_mod(prime[i],sum+1,MOD)-1)/(prime[i]-1);
        }
    }
    if(n > 1)
        ans *= (n*n-1)/(n-1);
    return ans;
}
int main()
{
  int n;
  get_primes();
  cin >> n;
  cout <<factor_sum(n); 
  return 0;
}
//分解质因数
#include <iostream>
using namespace std;
int main()
{
    int n,n2;
    cout<<"请输入需要分解的质因数:" ;
    cin>>n;
    cout<<n<<"=";//输出等于号 
    n2=n;
    if(n<2){ 
    return 0;//n小于2返回自身 
    }
    cout<<"1*"; //输出 1* 
    for(int i=2;i*i<=n2;i++)//for循环穷举质因数       
    {
        while(n2%i==0)//while循环判断质因数 
        {
            n2=n2/i;//获得质因数 
            cout<<i;//返回质因数 
            if (n2!=1)//判断质因数 
            cout<<"*";//输出乘号 
        }
    }
    if(n2!=1){//判断质因数 
    cout<<n2;//输出质因数 
    }
    return 0;//返回 
}
//法2:
#include <bits/stdc++.h>
using namespace std;
int main()
{
 int n;
 cin>>n;
 int m=n;
 int flag=0;
 cout<<m<<"=";
 for(int i=2;i*i<=n;i++)
 {
  if(n%i==0)
  {
   int cnt=0;
   while(n%i==0)
   {
    n=n/i;
    cnt++;
   }
   if(flag==1) printf("*"); 
   if(cnt==1)
   {
    printf("%d",i);
   } 
   else
   {
    printf("%d^%d",i,cnt);
   }
   flag=1;
  }
  } 
    if(n>1)
 {
   if(flag==1)printf("*");
   printf("%d",n);
    }
 return 0;
}

寻找质数

质数判断&分解质数&质数筛法 - AcWing:看这一篇就够了,筛法的时间复杂度是根号n。

#include <iostream>//质数相关的而题目要注意0,1这两个数

using namespace std;

const int N = 1010;
bool st[N];
int cnt = 0,prime[N];
void get_primes(int x){
    for(int i = 2; i <= x; i++)
    {
        if(!st[i])                         
            prime[cnt++] = i;

        for(int j = 0; prime[j] <= x / i; j++)//“ 《= ”  
        {
            st[prime[j] * i] = true;
            if(i % prime[j] == 0)               
                break;
        }
    }
}
int main()
{
  int n,sum = 0;
  cin >> n;
  get_primes(n);
  for(int i = 2;i <= n;i ++)
    if(!st[i]){
      cout << i << " ";sum ++;
  }
  cout << endl;
  cout << sum;
  return 0;
}

快速幂

AcWing 875. 快速幂—含快速幂思想的解释 - AcWing

#include <iostream>
using namespace std;

const int N = 1010;
bool st[N];
int cnt = 0,prime[N];
void get_primes(int x){
    for(int i = 2; i <= x; i++)
    {
        if(!st[i])                         
            prime[cnt++] = i;

        for(int j = 0; prime[j] <= x / i; j++)  
        {
            st[prime[j] * i] = true;
            if(i % prime[j] == 0)               
                break;
        }
    }
}
int main()
{
  int n,sum = 0;
  cin >> n;
  get_primes(n);
  for(int i = 2;i <= n;i ++)
    if(!st[i]){
      cout << i << " ";sum ++;
  }
  cout << endl;
  cout << sum;
  return 0;
}

求逆元

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;


LL qmi(int a, int b, int p)
{
    LL res = 1;
    while (b)
    {
        if (b & 1) res = res * a % p;
        a = a * (LL)a % p;
        b >>= 1;
    }
    return res;
}


int main()
{
    int n;
    scanf("%d", &n);
    while (n -- )
    {
        int a, p;
        scanf("%d%d", &a, &p);
        if (a % p == 0) puts("impossible");
        else printf("%lld\n", qmi(a, p - 2, p));
    }

    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值