数论整理(部分)

埃式筛法&欧拉筛法

学习资料:素数_埃氏筛法&&线性筛(欧拉筛法)【详解】

埃式筛法

#include <cstdio>
using namespace std;
typedef long long LL;
const int N = 1e8 + 10;
bool isprime[N];
int cnt;
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) isprime[i] = 1;
	isprime[0] = isprime[1] = 0;
	for (int i = 2; i <= n; i++)
	{
		if (isprime[i])
		{
			for (int j = i * i; j <= n; j += i)
			{
				isprime[j] = 0;
			}
		}
		if (isprime[i]) cnt++;
	}
	printf("%d\n", cnt);
}

欧拉筛法

int cntprime = 0;
for (int i = 2; i <= n; i++)
{
    if (!flag[i]) prime[++cntprime] = i;           //若未被筛去,说明是质数
    for (int j = 1; j <= cntprime && prime[j] * i <= n; j++)
    {
        flag[i * prime[j]] = true;       //标记号
        if (i % prime[j] == 0)           //prime[j]保证只被筛去一次
            break;
    }
}

质数分布

在这里插入图片描述

GCD&EXGCD

GCD

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

gcd的返回值为a,b两数的最大公因数
lcm(a,b)=a/gcd(a,b)*b; //lcm为a,b两数的最小公倍数,先除再乘是为了防止溢出

EXGCD

学习资料:https://blog.csdn.net/erin_jwx/article/details/107729239

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

快速幂

int Pow(int a, int b)
{
	int ans = 1;
	int base = a;
	while (b)
	{
		if (b & 1) ans *= base;
		base *= base;
		b >>= 1;
	}
	return ans;
}

逆元

x 在模 m 意义下的逆元 y 满足 xy ≡ 1(mod m) 。
存在逆元的条件是 gcd(x,m) = 1 。
求逆元的方法有三种:利用 exgcd,利用费马小定理,线性预处理。(暂时只学了exgcd求法,剩下两个之后再补)

拓展gcd求逆元

xy ≡ 1(mod m)
xy + am = 1
解出这个方程的一组解 (y,a) 即可。

找到a,b代入exgcd模板即可。
例:找x在模m下的逆元y,则a=x,b=m

中国剩余定理(CRT)

在这里插入图片描述
CRT板题:P1495 【模板】中国剩余定理(CRT)/曹冲养猪

#include <cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
void exgcd(LL a, LL b, LL &d, LL &x, LL &y)
{
	if (!b) { d = a; x = 1; y = 0; }
	else { exgcd(b, a%b, d, y, x); y -= x * (a / b); }
}
const int N = 1e5 + 10;
LL m[N];
LL mul=1;
LL M[N];
LL a[N];
LL ans;
int main()
{
	LL  d=0, x, y;
	LL n;
	scanf("%lld", &n);
	for(LL i=0;i<n;i++)
	{
		scanf("%lld %lld", &m[i],&a[i]);
		mul *= m[i];
	}
	for (LL i = 0; i < n; i++)
	{
		M[i] = mul / m[i];
		exgcd(M[i], m[i], d, x, y);
		ans += a[i] * M[i] * (x < 0 ? x+m[i] : x);
	}
	printf("%lld\n", ans%mul);
}

欧拉函数&欧拉定理

欧拉函数

欧拉函数是小于x的整数中与x互质的数的个数,一般用φ(x)表示。特殊的,φ(1)=1。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200802154102806.png
pi为n的质因数,n为正整数

求一个数的欧拉函数值

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

求多个数的欧拉函数值
用phi[x]表示φ(x)

void euler(int n)
{
    for (int i=1;i<=n;i++) phi[i]=i;
    for (int i=2;i<=n;i++)
    {
        if (phi[i]==i)//这代表i是质数
        {
            for (int j=i;j<=n;j+=i)
            {
                phi[j]=phi[j]/i*(i-1);//把i的倍数更新掉
            }
        }
    }
}

欧拉定理

欧拉定理
在这里插入图片描述

拓展欧拉定理
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值