一、质数问题
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);
}
}