素数 快速幂 gcd.lcm

一 素数

1.判断一个数是不是素数 如果x<=1 则不是素数 是素数返回true 不是则返回false

bool is_pri(ll x)     //时间复杂度O(√n)
{
    ll s=sqrt(x+0.5);       //加0.5是为了防止精度误差
    for(ll i=2;i<=s;i++)
        if(!(x%i)) return false;
    return true;
}
bool is_pri(ll x)    //时间复杂度O(√n)
{
    for(ll i=2;i*i<=x;i++)   //不用sqrt()来确定最大值  避免精度误差
        if(!(x%i)) return false;
    return true;
}

2.素数筛选法 找出1-n的所有素数
埃筛 : 埃拉托斯特尼筛法,或者叫埃氏筛法
原理 : 一个素数的倍数不是素数

const int N=1e6+7;
int vis[N]={0};  //vis[i]=0 i为素数 vis[i]=1 i不为素数
void prime()  //时间复杂度 O(nloglogn)
{
    vis[0]=1;
    vis[1]=1;
    for(int i=2;i<N;i++)
        if(!vis[i])
            for(int j=2*i;j<N;j+=i)
                vis[j]=1;
}

埃筛优化

void prime()
{
    vis[0]=1;
    vis[1]=1;
    for(int i=2;i*i<N;i++)
        if(!vis[i])
            for(int j=i*i;j<N;j+=i)
                vis[j]=1;
}

二 快速幂
1.求x^y
(1)

const ll mod=1e9+7;
ll quick(ll x,ll y)
{
    ll ans=1;
    while(y)
    {
        if(y%2) ans=(ans*x)%mod;
        x=(x*x)%mod;
        y/=2;
    }
    return ans;
}

(2)位运算形式

ll quick(ll x,ll y)
{
    ll ans=1;
    while(y)
    {
        if(y&1) ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans;
}

(3) 衍生 快速乘

ll quick_mul(ll x,ll y)
{
    ll ans=0;
    while(y)
    {
        if(y&1) ans=(ans+x)%mod;
        x=(x+x)%mod;
        y>>=1;
    }
    return ans;
}

三gcd lcm

algorithm 里面有__gcd(a,b)内置函数
gcd原理 辗转相除法

ll gcd(ll a,ll b)
{
    ll tmp;
    while(b)
    {
        tmp=b;
        b=a%b;
        a=tmp;
    }
    return a;
}

gcd 衍生

(1) lcm(a,b)=a/gcd(a,b)*b; //先除后乘 避免乘法溢出

(2) gcd(k*a,k*b)=k*gcd(a,b);

(3) lcm(k*a,k*b)=k*lcm(a,b);
推导lcm(k*a,k*b)=(k*a)/(k*gcd(a,b))(k*b)=k(a/gcd(a,b)*b)=k*lcm(a,b);

(4)除法:lcm(S/a,S/b)=S/gcd(a,b);

猜你喜欢

转载自blog.csdn.net/oinei/article/details/76457161