数论整理笔记

一、质数问题

1、欧拉函数

在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目)

​
int phi[1000010];
 
void Euler_excel(int n)//n是打表打到多少
{
   phi[1]=0;
   for(int i=2;i<=n;i++) phi[i]=0;
   for(int i=2;i<=n;i++)
      if(!phi[i]){
          for(int j=i;j<=n;j+=i){
             if(!phi[j])  phi[j]=j;
             phi[j]=phi[j]/i*(i-1);
          }
      }
}

​

2、埃筛

收集素数

int prime[SIZE];            // 第i个素数
bool is_prime[SIZE];    //true表示i是素数

int slove(int n)
{
    int p = 0;
    for(int i = 0; i <= n; i++)
        is_prime[i] = true;             //初始化
    is_prime[0] = is_prime[1] = false;      //0,1不是素数
    for(int i = 2; i <= n; i++)
    {
        if(is_prime[i])                //这里比较巧妙
        {
            prime[p++] = i;             //计算素数的个数,也记录下了素数
            for(int j = 2 * i; j <= n; j += i)      // 除掉了i的倍数的数字
                is_prime[j] = false;
        }
    }
    return p;
}

二、欧几里得相关数学知识(欧几里得、裴蜀、扩展欧几里得)

1、欧几里得定理

欧几里得定理即为 gcd(a,b)=gcd(b,a%b)。

gcd(x,y)=gcd(x-y,y)=gcd(y,x%y)

该定理常用于计算最大公约数。

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

2、裴蜀定理

gcd(a,b)=ax+by;(存在整数x,y使等式成立,x,y可以是复数)

该表达式可以拓展到无限,gcd(gcd(a,b),c)=ax+by+cz等等;

3、同余问题

ax≡1(modb) ->  axmodb=1,它的实质是 ax + by = 1ax+by=1

把1推广到m:方程 ax + by = m有解的必要条件是 m mod gcd(a,b) = 0。

求关于x的同余方程ax≡1(modb) 的最小正整数解。
输入格式
一行,包含两个正整数 a,b,用一个空格隔开。
输出格式
一个正整数 x0,即最小正整数解。输入数据保证一定有解。
输入输出样例
输入 
3 10
输出 
7
#include<bits/stdc++.h>
using namespace std;

long long x, y;//目前方程真正的解 

void exgcd(long long a, long long b)
{
	//当前目的:求解 ax + by = gcd(a, b) 这么一个方程
	
	if(b == 0) //a, b不断改变的过程中,b最终必然会成为0
	{
		//在 b = 0 时方程还要成立? 使 x = 1, y = 0 ,必然成立 
		x = 1;
		y = 7; //建议返回0。不过y = 7能AC,证明了最后一个等式不受最后一个y影响
		return;
	} 
	
	exgcd(b, a % b);//把下一层系数传进去(先求下一个方程的解 )
	
	//现在我们已经拿到了下一个方程的解x, y
	long long tx = x;//暂时存一下x,别丢了
	x = y;
	y = tx - a / b * y; 
}

int main()
{
	long long a, b;
	cin >> a >> b;
	exgcd(a, b);
    
	x = (x % b + b) % b;//我们求出来的x必然满足方程,但不一定是最小正整数解,所以要进行答案处理
	printf("%lld\n", x);
	return 0;
}

4、扩展欧几里得

扩展欧几里得算法是用来在已知 a, b 的情况下求解一组 x,y,使它们满足等式ax+by=gcd(a,b)=kd(注意:gcd(a, b) | d)该方程的解一定存在

#include<iostream>
#include<cstdio>
using namespace std;

typedef long long LL; 

void extend_Eulid(LL a, LL b, LL &x, LL &y, LL &d){
    if (b == 0) {d = a, x = 1, y = 0;}
    else{
        extend_Eulid(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}

int main(){
    LL a, b, d, x, y;
    while(~scanf("%lld%lld", &a, &b)){
        extend_Eulid(a, b, x, y, d);
        printf("%lld*a + %lld*b = %lld\n", x, y, d);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值