数论板子(自用,待更新)


/**-------------------------快速幂-------------------------*/

///快速幂取余,O(logb),底数越大速度慢的越快
const int mod = 1e9+7;
ll quick_pow(ll a,ll b){
    ll ans = 1;
    while(b){
        if(b&1) ans = (ans * a)%mod;
        b>>=1;
        a = (a * a)%mod;
    }
    return ans;
}


///矩阵快速幂取余,O(mnlogb)
const int mod = 1e9+7;
struct matrix{
    static const ll maxn = 4;
    ll mat[maxn][maxn];
    ll n,m;
    matrix(ll _n = maxn,ll _m = maxn):n(_n),m(_m){memset(mat,0,sizeof(mat));}//初始化n阶零矩阵
    void I(){for(int i = 0;i>=1;
        a = a * a;
    }
    return ans;
}

/**-------------------------素数判断-------------------------*/

///试除法,O(n^1/2),若是合数,那么在[1,sqrt(n)]中至少有一个质因子
bool isPrime_naive(int n){
    if(n == 2) return 1;
    if(n == 1) return 0;
    for(int i = 2;i*i<=n;i++) if(!(n%i)) return 0;
    return 1;
}


///kn+i法,k=30,O(n^2/15),kn+i中的i = 1,7,11,13,17,19,23,29时,kn+i的值才可能成为待判数字的质因子
bool isPrime_kni(int n){
    if(n == 2 || n == 3 || n == 5) return 1;
    if(n == 1 || !(n%2) || !(n%3) || !(n%5)) return 0;
    ll a[8] = {4,2,4,2,4,6,2,4},p = 0;//下一个数字的增量
    for(int i = 7;i*i<=n;i+=a[p++],p%=8) if(!(n%i)) return 0;
    return 1;
}


///预处理法,对于多组数据,如果n是合数就一定有在[1,n^1/2]的质因子,先预处理出[1,n^1/2]的所有素数,然后对n测试

/**-------------------------素数筛-------------------------*/

///埃氏筛,O(nloglogn),通过标记素数的倍数筛掉合数
const int N = 1e6+7;
bool vis[N];
int prime[N],cnt;
void eratosthenes_screen(int n){
    for(int i = 2;i<=n;i++){
        if(vis[i]) continue;
        prime[cnt++] = i;
        for(int j = 2;j*i<=n;j++) vis[i*j] = 1;
    }
}


///欧拉筛(线性筛),O(n),每个合数只会被最小质因子筛掉
const int N = 1e6+7;
bool vis[N];
int prime[N],cnt;
void euler_screen(int n){
    for(int i = 2;i<=n;i++){
        if(!vis[i]) prime[cnt++] = i;
        for(int j = 0;j> 1,b >> 1) << 1;//最后要把因子2乘上
    else if(a&1 && !(b&1)) return stein_recursion(a,b >> 1);
    else if(!(a&1) && b&1) return stein_recursion(a >> 1,b);
    else return stein_recursion(a - b,b);
}
//迭代版
int stein_iteration(int a,int b){
    int k = 1;
    while(!(a&1) && !(b&1)) k<<=1,a>>=1,b>>=1;//k记录因子2乘积
    while(!(a&1)) a>>=1;
    while(!(b&1)) b>>=1;
    if(a