数论基础模板

来源:互联网 发布:占卜软件哪个好 编辑:程序博客网 时间:2024/05/22 02:26

中国剩余定理

这里写图片描述

//模板int exgcd(int a,int b,int &x,int &y)    //扩展欧几里得算法 c = ax + by   gcd(a,b)|c{    if(b==0)    {        x=1;        y=0;        return a;    }    int d = exgcd(b,a%b,y,x);    y -= a/b*x;    return d;}int ChineseRemainder(int a[],int w[],int len)    // a[]存放余数  w[]存放两两互质的数{    int x,y,m,n=1,ret=0;    for (int i=0; i<len; i++)        n *= w[i];    for (int i=0; i<len; i++)    {        m = n/w[i];        int d = exgcd(w[i],m,x,y);        ret = (ret+y*m*a[i])%n;    }    return (n+ret%n)%n;}

快速幂取模

long long  PowMod(long long a,long long n,long long m) // a^n%m{    long long res = 1;    while( n!=0 )    {        if (n&1)            res = res * a % m;        a =a*a%m;        n = n>>1;    }    return res;}

欧拉函数

对正整数n,欧拉函数表示小于n的正整数中与n互质的数的数目 φ(1)=1

const int N = 1000005;int phi[N];vector<int> prime;void init()  //欧拉函数筛  O(n) + O(1)int main(){    phi[1] = 1;    for(int i=2; i<N; i++)    {        if(phi[i] == 0)        {            prime.push_back(i);            phi[i] = i-1;        }        for(int j=0; j<prime.size() && prime[j]*i<N; j++)        {            if(i%prime[j] == 0)            {                phi[i*prime[j]] = phi[i] * prime[j];                break;            }            else                phi[i*prime[j]] = phi[i] * (prime[j]-1);        }    }}

费马小定理

费马小定理

组合数

C(n,m) = n! / ( (n-m)! * m! )(n>=m)

long long  Cnm(int n, int m)// n个中取m个{    if (m == 0)        return 1;    long long  up = 1;    long long  down = 1;    for (int i=0; i<m; i++)    {        up *= (n - i);        down *= (i + 1);    }    return up / down;}

全错位排序

一个人写了n封不同的信及相应的n个不同的信封,他把这n封信都装错了信封,问都装错信封的装法有多少种?
由递推公式得

long long  f[30];void init(){    for(int i=2; i<=25; i++)    {        if(i & 1)            f[i] = i * f[i-1] - 1;        else            f[i] = i * f[i-1] + 1;    }}

第一类斯特林数

把一个包含n个元素的集合分成k个环排列的方法数。
假设已经推出了n-1个元素分成k个环的方法数以及n-1个元素分成k-1个环的元素,我们考虑第n个元素,一种情况是这个元素自己成环,于是是S(n-1,k-1),另一种情况是把这个元素放到任意一个元素的左边,方案数是(n-1)S(n-1,k).
初始值
S[n][0] = 0, S[1][1] = 1;
递推公式
S[n][k] = S(n-1,k-1) + (n-1)S(n-1,k)

long long stir[maxn][maxn];void init(){    stir[1][1] = 1;    for(int i=2; i<maxn; i++)        for(int j=1;j<=i; j++)            stir[i][j] = stir[i-1][j-1] + (i-1) *stir[i-1][j];}

第二类斯特林数

把一个包含n个元素的集合分成k个非空子集的方法数。
考虑第n个元素,如果它自成一个集合,那么前n-1个元素构成k-1个集合,就是S(n,k),如果它不是自成集合,那么前面n-1个元素构成k个集合,再把第n个元素加到任意一个集合中,共k种方案。
初始值 S[n][0]=0, S[n][k]=0 (n

Lucas

C(n,m)%p=C(n/p,m/p) * C(n%p,m%p) % p p为素数

long long fac[maxn];void init(long long mod){    fac[0] = 1;    for(int i=1; i<=mod; i++)        fac[i] = fac[i-1] * i % mod;}long long lucas(long long n, long long m, long long p){    long long ret = 1;    while(n && m)    {        long long a = n%p;        long long b = m%p;        if(a < b)            return 0;        ret = (ret * fac[a] * PowMod(fac[b]*fac[a-b]%p, p-2, p)) %p;        n /= p;        m /= p;    }    return ret;}
原创粉丝点击