埃式筛法&欧拉筛法
埃式筛法
#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。
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的倍数更新掉
}
}
}
}
欧拉定理
欧拉定理
拓展欧拉定理