欧拉筛
int s[maxn],p[maxn];
void prime(int n){
int cnt=0;
for(int i=2;i
6k+/-1
质数的分布具有特点,经过证明可以得到:(大于等于5的)质数一定和6的倍数相邻,一定是6x-1或6x+1。利用这种特性。可以对整数进行筛选,只判断那些是6x-1或6x+1的整数是否为质数。
bool Prime(int n) {
if (n<=3)
return n > 1;
if (n==4) return false;
// 只有6x-1和6x+1的数才有可能是质数
if (n % 6 != 1 && n % 6 != 5)
return false;
// 判断这些数能否被小于sqrt(n)的奇数整除
int t = (int) sqrt(n);
for (int i = 5; i <= t; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
ll fastPower(ll x, ll n,ll p) {
ll res = 1;
x%=p;
while (n){
if(n & 1) res = (res * x )%p;
n >>= 1;
x = (x * x)%p ;
}
return res;
}
存在判断: a和p互质,即
g c d ( a , p ) = 1 gcd(a,p)=1 gcd(a,p)=1
当p为质数,利用费马最小定理:
ll get_inv(ll x,ll p){
return fastPower(x,p-2,p);
}
利用扩展欧几里得算法
求
a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
的一组x,y
补充:欧几里得法求最大公约数
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void exgcd(int a,int b,int &x,int &y){
if(b==0){x=1;y=0;}
int gcd=exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
int get_inv(int a,int p){
int x=1,y=0;
exgcd(a,p,x,y);
return (x%p+p)%p;//防止出现负数
}
线性求逆元(直接求出1~n个)
int inv[maxn];
inv[1]=1;
for(int i=2;i<=n;i++){
inv[i]=-(p/i)*inv[p%i];//x_inv=-k*r_inv;(推导公式)
inv[i]=(inv[i]%p+p)%p;//保证该值一定为正
}