1. 程式人生 > >ACM數學常用知識整理(持續更新ing)

ACM數學常用知識整理(持續更新ing)

1.最大公約數,最小公倍數

int gcd(int x,int y)
{
    int z=y;
    while(x%y!=0)
    {
        z=x%y;
        x=y;
        y=z;
    }
    return z;
}
int lcm(int x,int y)
{
    return x*y/gcd(x,y);
}

2.快速冪

int qpow(int a,int b,int mod)//a^b
{
    int t=1;
    while(b)
    {
        if(b&1)
        {
            t=(t*a)%mod;
            b--;
        }
        a=(a*a)%mod;
        b>>=1;
    }
    return t;

>>矩陣快速冪 很久以前收集的模板,親測可用

struct Matrix
{
    int m[3][3];
};

Matrix Mul(Matrix a,Matrix b)
{
    Matrix c;
    memset(c.m,0,sizeof(c.m));
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            for(int k=0;k<3;k++)
                c.m[i][j] += ((a.m[i][k]*b.m[k][j])%SMod + SMod)%SMod;
    return c;
}

Matrix fastm(Matrix a,int n) 
{
    Matrix res;
    memset(res.m,0,sizeof(res.m));
    res.m[0][0] = res.m[1][1] = res.m[2][2] = 1;
    while(n)
    {
        if(n&1)
            res = Mul(res,a);
        n>>=1;
        a = Mul(a,a);
    }
    return res;
}

Matrix MPow(Matrix a,int n)  //第二種寫法,慎用,易RE
{
    if(n == 1)
        return a;
    Matrix res = fastm(a,n/2);
    res = Mul(res,res);
    if(n&1)
        res = Mul(res,a);
    return res;
}

 另外一種

struct Matrix
{
    lll m[13][13];
    Matrix()
    {
        memset(m,0,sizeof(m));
        for(int i=1;i<=n+2;i++)
            m[i][i] = 1LL;
    }
};

Matrix Mul(Matrix a,Matrix b)
{
    Matrix res;
    int i,j,k;
    for(i=1;i<=n+2;i++)
    {
        for(j=1;j<=n+2;j++)
        {
            res.m[i][j] = 0;
            for(k=1;k<=n+2;k++)
                res.m[i][j] = (res.m[i][j]+(a.m[i][k]*b.m[k][j])%SMod + SMod)%SMod;
        }
    }
    return res;
}

Matrix fastm(Matrix a,int b)
{
    Matrix res;
    while(b)
    {
        if(b&1)
            res = Mul(res,a);
        a = Mul(a,a);
        b >>= 1;
    }
    return res;
}

 對元素0較多的矩陣取快速冪時可在Mul函式中加一個小優化:

Matrix Mul(Matrix a,Matrix b)
{
    Matrix res;
    int i,j,k;
    memset(res.m,0,sizeof(res.m));
    for(k=1;k<=n+2;k++)
    {
        for(i=1;i<=n+2;i++)
        {
            if(a.m[i][k])
            {
                for(j=1;j<=n+2;j++)
                    res.m[i][j] = (res.m[i][j]+(a.m[i][k]*b.m[k][j])%SMod + SMod)%SMod;
            }
        }
    }
    return res;
}

3.排列組合

LL A(int n,int m)//n>=m
{
    int ans=1;
    if(n<m)return 0;
    while(m--)
    {
        ans*=n;
        n--;
    }
    return ans;
}
LL C(int n,int m)
{
    if(n<m)return 0;
    return A(n,m)/A(m,m);
}

 組合數性質:從這看到的:https://blog.csdn.net/litble/article/details/75913032

4.錯排

D(n) = (n-1) [D(n-2) + D(n-1)](n物品全部錯位的方案數)

D(n) = n! [(-1)^2/2! + … + (-1)^(n-1)/(n-1)! + (-1)^n/n!].

記住公式就知道程式碼了

5.費馬小定理: 假如p是質數,且gcd(a,p)=1,那麼 a^(p-1)≡1(mod p)。(如果a為整數,p為質數,a和p互質,則a的p-1次冪對p取模永遠等於1)