模板 - 数学 - 数论

快速幂

//快速幂 x^n%p
ll qpow(ll x,ll n){
    ll res=1;
    while(n){
        if(n&1) res=res*x%p;
        x=x*x%p;
        n>>=1;
    }
    return res%p;
    //要记得模p,否则输入一个2的幂次模1就挂了
}

 

快速乘

//快速乘 a*b%p 防止乘法溢出ll
ll qmut(ll a,ll b,ll p){
    ll res=0;
    while(b){
        if(b&1) res=(res+a)%p;
        a=(a+a)%p;
        b>>=1;
    }
    return res;
}

 

 

费马大定理

欧拉定理

欧拉函数 积性

 

 

 

d(n)n的因子个数

\sigma(n) n的因子之和

 

这些都是积性的

 

狄利克雷卷积

设函数 $f(x)$ 和 $g(x)$ ,则他们的狄利克雷卷积 $f*g(x)=\sum\limits_{d|x}f(d)g(\frac{x}{d})$

两个积性函数的狄利克雷卷积也是积性的

 

杜教筛

 

扩展欧几里得算法:

//扩展欧几里得算法:返回 g=gcd(a,b) ,以及对应的等式 ax+by=g 的解
ll extend_gcd(ll a,ll b,ll &x,ll &y){
    if(a==0&&b==0)
        return -1;
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    ll d=extend_gcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

//扩展欧几里得算法求逆元,只要求 a,mod 互质
ll inv2(ll a,ll mod){
    ll x,y;
    ll d=extend_gcd(a,mod,x,y);
    if(d==1)
        return (x%mod+mod)%mod;
    return -1;
}

 

更快的判断单独判断素数:

bool is_prime(int n)
{
    if(n==1) return false;
    if(n==2||n==3) return true;
    if(n%6!=1&&n%6!=5) return false;
    for(int i=5;i*i<=n;i+=6)
        if(n%i==0||n%(i+2)==0) return false;
    return true;
}

接近原本判断法的2倍速度。

 

线性筛/欧拉筛

const int MAXN=10000;
bool is_prime[MAXN+5];
int prime[MAXN+5], cntp = 0;
//实际上素数的个数大约是MAXN/ln(MAXN)个

void get_prime(int n) {
    memset(is_prime,1,sizeof(is_prime));
    is_prime[0]=is_prime[1]=0;
    for(int i =2; i<=n; i++) {
        if(is_prime[i])
            prime[cntp++]=i;
        for(int j=0; j<cntp&&i*prime[j]<= n; j++) {
            is_prime[i*prime[j]]=0;
            if(i%prime[j]==0)
                break;
        }
    }

    //printf("cntp=%d\n",cntp);
    /*for(int i=0;i<=n;i++){
        if(is_prime[i])
            printf("%d ",i);
    }*/
}

 

posted @ 2019-03-18 16:49  韵意  阅读(161)  评论(0编辑  收藏  举报