• 数论模板


    组合数

      递推

    void get_C()
    {
        for(int i=0;i<=2005;i++)
        {
            C[0][i]=C[i][i]=1;
            for(int j=1;j<i;j++)
            {
                C[j][i]=(C[j-1][i-1]+C[j][i-1])%MOD;
            }
        }
    }
    View Code

      虎爷版

    int f[10000+10];LL pf[10000+10];
    LL qmod(LL a, LL b)
    {
        if (b == 0) return 1;
        LL r = a % MOD;
        LL k = 1;
        while (b > 1){
            if ((b & 1)!=0)
                k = (k * r) % MOD;
            r = (r * r) % MOD;
            b >>= 1;
        }
        return (r * k) % MOD;
    }
    void init(){
        f[0]=1;
        for(int i=1;i<=maxn;i++){
            f[i]=(long long)f[i-1]*i%MOD;
            pf[i]=qmod(f[i],MOD-2);
        }
    }
    
    int C(int n,int m){
        if(n==m||m==0)return 1;
        return ((long long)f[n]*qmod(f[m],MOD-2)%MOD)*qmod(f[n-m],MOD-2)%MOD;
    }
    View Code

       杜教版

    int fac[maxn], inv[maxn];
    long long qmod(int a, int b)
    {
        long long ret = 1;
        for(; b; b >>= 1, a = (long long)a * a % MOD)
            if(b & 1)
                ret = ret * a % MOD;
        return ret;
    }
    void init()
    {
        fac[0] = 1;
        for(int i = 1; i < maxn; i++)
            fac[i] = (long long)fac[i - 1] * i % MOD;
        inv[maxn - 1] = qmod(fac[maxn - 1], MOD - 2);
        for(int i = maxn - 1; i > 0; i--)
            inv[i - 1] = (long long) inv[i] * i % MOD;
    }
    long long C(int n, int m)
    {
        if(n < 0 || m < 0 || m > n)
            return 0;
        return (long long)fac[n] * inv[m] % MOD * inv[n - m] % MOD;
    }
    View Code

    埃氏筛法

    const int maxn = 1e+6 + 7;
    bool prime[maxn];
    int rec[maxn], cnt;
    void init_prime()
    {
        cnt = 0;
        memset(prime, true, sizeof(prime));
        prime[0] = prime[1] = false;///表明true为质数
        for (int i = 2; i <= maxn; ++i){
            if (prime[i]) rec[cnt++] = i;
            //此处边界判断为rec[j] <= maxn / i,如果写成i * rec[j] <= maxn,需要确保i * rec[j]不会溢出int
            for (int j = 0; j < cnt && rec[j] <= maxn / i; ++j){
                prime[i * rec[j]] = false;
                if (i % rec[j] == 0)
                    break;
            }
        }
    }
    View Code

    快速幂

      取模

    LL qmod(LL a, LL b)
    {
        if (b == 0) return 1;
        LL r = a % MOD;
        LL k = 1;
        while (b > 1){
            if ((b & 1)!=0)
                k = (k * r) % MOD;
            r = (r * r) % MOD;
            b >>= 1;
        }
        return (r * k) % MOD;
    }
    View Code

      不取模

    LL qmod(LL a, LL b)
    {
        if (b == 0) return 1;
        LL r = a;
        LL k = 1;
        while (b > 1){
            if ((b & 1)!=0)
                k = (k * r);
            r = (r*r);
            b >>= 1;
        }
        return r*k;
    }
    View Code

      传模数

    LL qmod(LL a, LL b,LL p)
    {
        if (b == 0) return 1;
        LL r = a % p;
        LL k = 1;
        while (b > 1){
            if ((b & 1)!=0)
                k = (k * r) % p;
            r = (r * r) %p;
            b >>= 1;
        }
        return (r * k) % p;
    }
    View Code

    快速乘

      lgn

    LL mult(LL A,LL B)
    {
        LL z = 0;
        if (B == 0) return z;
        z = mult(A,B >> 1);
        z = (z << 1) % mod;
        if (B & 1) z = (z + A) %mod;
        return z;
    }
    View Code

      O(1)

    //O(1)快速乘
    inline LL quick_mul(LL x,LL y,LL MOD){
        x=x%MOD,y=y%MOD;
        return ((x*y-(LL)(((long double)x*y+0.5)/MOD)*MOD)%MOD+MOD)%MOD;
    }
    View Code

    自适应积分

    double const eps=1e-6;
    double F(double x)
    {
        return 1.0/sqrt(1.0+x*x);
    }
    double simpson(double a,double b)
    {
        double c = a + (b-a)/2;
        return (F(a)+4*F(c) + F(b)) * (b-a)/6;
    }
    double asr(double a,double b,double eps,double A)
    {
        double c = a + (b-a)/2;
        double L = simpson(a,c),R = simpson(c,b);
        if(fabs(L + R - A) <= 15*eps)return L + R + (L + R - A)/15.0;
        return asr(a,c,eps/2,L) + asr(c,b,eps/2,R);
    }
    double asr(double a,double b,double eps)
    {
        return asr(a,b,eps,simpson(a,b));
    }
    ///printf("%.6f
    ",asr(0,n,eps));
    View Code

    欧拉函数

      筛法

    #define maxn 1000001
    int euler[maxn];
    void Init(){
         euler[1]=1;
         for(int i=2;i<maxn;i++)
           euler[i]=i;
         for(int i=2;i<maxn;i++)
            if(euler[i]==i)
               for(int j=i;j<maxn;j+=i)
                  euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出
    }
    View Code

      求单值

    //直接求解欧拉函数  
    int euler(int n){ //返回euler(n)   
         int res=n,a=n;  
         for(int i=2;i*i<=a;i++){  
             if(a%i==0){  
                 res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出   
                 while(a%i==0) a/=i;  
             }  
         }  
         if(a>1) res=res/a*(a-1);  
         return res;  
    }  
    View Code

    扩展欧几里得

      常规扩欧

    LL ex_gcd(LL a,LL b,LL &x,LL &y)
    {
        if(b==0){
            x=1;y=0;
            return a;
        }
        LL r=ex_gcd(b,a%b,y,x);
        y-=x*(a/b);
        return r;
    }
    View Code

      扩欧求逆元

    int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0){x=1,y=0;return a;}
        int ans=exgcd(b,a%b,y,x);
        y-=a/b*x;
        return ans;
    }
    int inv(int a,int p)
    {
        int x,y;
        int g=ecgcd(a,p,x,y);
        if(1%g!=0) return -1;
        x*=1/g;
        p=abs(p);
        int ans=x%p;
        if(ans<=0)ans+=p;
        return ans;
    }
    View Code

    牛顿迭代求开方

    const double eps=1e-9;
    double sqr(double x)
    {
        double k=x;
        while(k*k-x>eps)
            k=0.5*(k+x/k);
        return k;
    }
    View Code

    错排公式

    ///f[i] pf[i]代表阶乘表和阶乘逆元表
    LL solve(int x)
    {
        LL res=0;
        for(int i=2;i<=x;i++){
            LL as=(f[x]*pf[i])%MOD;
            if(i&1){
                res=(res-as+MOD)%MOD;
            }
            else res=(res+as)%MOD;
        }
        return res;
    }
    View Code

    第二类斯特林数

    int s2[maxn][maxn];
    void init_s2()
    {///s2[i][j]代表把i个数划分到j个集合中
        for(int i=1;i<maxn;i++){
            s2[i][1]=s2[i][i]=1;
            for(int j=2;j<i;j++){
                s2[i][j]=(s2[i-1][j-1]+(long long)j*s2[i-1][j]%MOD)%MOD;
            }
        }
    }
    View Code

     质因数分解

    void factor(LL n,LL a[maxn],LL b[maxn],int &tot) {
        LL temp,now,i;
        temp=(int)((double)sqrt(n)+1);
        tot=0;
        now=n;
        for(i=2;i<=temp;i++) {
            if(now%i==0) {
                a[++tot]=i;
                b[tot]=0;
                while(now%i==0) {
                    ++b[tot];
                    now/=i;
                }
            }
        }
        if(now!=1) {
            a[++tot]=now;
            b[tot]=1;
        }
    }
    View Code

    FFT

      namespace封装

    namespace FFT {
        struct comp {
            double r, i;
            explicit comp(double r = 0.0, double i = 0.0) : r(r), i(i) {}
            inline friend comp operator +(comp a, comp b) {
                return comp(a.r + b.r, a.i + b.i);
            }
            inline friend comp operator -(comp a, comp b) {
                return comp(a.r - b.r, a.i - b.i);
            }
            inline friend comp operator *(comp a, comp b) {
                return comp(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r);
            }
            inline friend comp operator /(comp a, double b) {
                return comp(a.r / b, a.i / b);
            }
        };
        const double pi = acos(-1);
        const int N = 5e5 + 10;
        int rev[N];
        inline void fft(comp *p, int n, int idft) {
            for (int i = 0; i < n; i++)
                if (i < rev[i])
                    std::swap(p[i], p[rev[i]]);
            for (int j = 1; j < n; j <<= 1) {
                static comp wn1, w, t0, t1;
                wn1 = comp(cos(pi / j), idft * sin(pi / j));
                for (int i = 0; i < n; i += j << 1) {
                    w = comp(1, 0);
                    for (int k = 0; k < j; k++) {
                        t0 = p[i + k];
                        t1 = w * p[i + j + k];
                        p[i + k] = t0 + t1;
                        p[i + j + k] = t0 - t1;
                        w = w * wn1;
                    }
                }
            }
            if (idft == -1) {
                for (int i = 0; i < n; i++)
                    p[i] = p[i] / n;
            }
        }
        template <typename T>
        inline T* fft_main(T *a, T *b, int n, int m) {
            static T res[N];
            static int nn, len;
            static comp aa[N], bb[N];
            len = 0;
            for (nn = 1; nn < m + n; nn <<= 1)
                len++;
            for (int i = 0; i < nn; i++) {
                aa[i] = comp(a[i], 0);
                bb[i] = comp(b[i], 0);
            }
            rev[0] = 0;
            for (int i = 1; i < nn; i++)
                rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
            fft(aa, nn, 1);
            fft(bb, nn, 1);
            for (int i = 0; i < nn; i++)
                aa[i] = aa[i] * bb[i];
            fft(aa, nn, -1);
            for (int i = 0; i < nn; i++)
                res[i] = aa[i].r + 0.5;
            return res;
        }
    }
    View Code

      手撕FFT(kuangbin版,不对逆元进行打表)

    const double PI=acos(-1.0);
    struct cp
    {
        double r,i;
        cp(){}
        cp(double _r,double _i)
        {
            r=_r;i=_i;
        }
        cp operator +(const cp &a)const
        {
            return cp(a.r+r,a.i+i);
        }
        cp operator -(const cp &a)const
        {
            return cp(r-a.r,i-a.i);
        }
        cp operator *(const cp &a)const
        {
            return cp(r*a.r-i*a.i,r*a.i+i*a.r);
        }
        cp conj()
        {
            return cp(r,-i);
        }
    };
    void change(cp y[],int len)
    {
        int i,j,k;
        for(i = 1, j = len/2;i < len-1;i++){
            if(i < j)swap(y[i],y[j]);
            k = len/2;
            while( j >= k){
                j -= k;
                k /= 2;
            }
            if(j < k)j += k;
        }
    }
    void fft(cp y[],int len,int on)
    {///on==1代表正fft,on==-1代表逆fft
        change(y,len);
        for(int h = 2;h <= len;h <<= 1){
            cp wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
            for(int j = 0;j < len;j += h){
                cp w(1,0);
                for(int k = j;k < j+h/2;k++){
                    cp u = y[k];
                    cp t = w*y[k+h/2];
                    y[k] = u+t;
                    y[k+h/2] = u-t;
                    w = w*wn;
                }
            }
        }
        if(on == -1)
            for(int i = 0;i < len;i++)
                y[i].r /= len;
        /**
        for(int i=0;i<as;i++){
                num[i]=(long long)(x[i].r+0.5);
        } ///整数最后需要这样取整,fft中最后已经还原nn
        */
    }
    View Code

      胡小兔(对逆元进行打表)

    const double PI=acos(-1.0);
    struct cp
    {
        double r,i;
        cp(){}
        cp(double _r,double _i)
        {
            r=_r;i=_i;
        }
        cp operator +(const cp a)const
        {
            return cp(a.r+r,a.i+i);
        }
        cp operator -(const cp a)const
        {
            return cp(r-a.r,i-a.i);
        }
        cp operator *(const cp a)const
        {
            return cp(r*a.r-i*a.i,r*a.i+i*a.r);
        }
        cp conj()
        {
            return cp(r,-i);
        }
    };
    int n=1,m;
    double q[N],res[N];
    cp f[N],f1[N],g[N],omg[N],inv[N];
    void FFT_init(){
        for(int i=0;i<n;i++){
            omg[i]=cp(cos(2*PI*i/n),sin(2*PI*i/n));
            inv[i]=omg[i].conj();
        }
    }
    /**
    在n倍增为长度2m长度时while(n<2*m)n*=2;
    才可以进行FFTinit;正向FFT时传omg,逆fft传inv
    计算结束后需要手动除n还原
    */
    void fft(cp *a,cp *omg){
        int lim=0;
        while((1 << lim) < n) lim++;
        for(int i=0;i<n;i++){
            int t=0;
            for(int j=0;j<lim;j++)
                if(i >> j&1) t |= 1 << (lim - j - 1);
            if(i<t) swap(a[i],a[t]);
        }
        for(int l=2;l<=n;l*=2){
            int m=l/2;
            for(cp *p=a;p!=a+n;p+=l){
                for(int i=0;i<m;i++){
                    cp t=omg[n/l*i]*p[m+i];
                    p[m+i]=p[i]-t;
                    p[i]=p[i]+t;
                }
            }
        }
    }
    View Code

    FWT

    void fwt(ll f[], int len, int op) {
        int n = (1 << len);
        for (int i = 1; i <= len; ++i) {
            int m = (1 << i), len = m >> 1;
            for (int r = 0; r < n; r += m) {
                int t1 = r, t2 = r + len;
                for (int j = 0; j < len; ++j, ++t1, ++t2) {
                    ll x1 = f[t1], x2 = f[t2];
                    if (op == 1) {   //xor
                        f[t1] = x1 + x2;
                        f[t2] = x1 - x2;
                        //if(f[t1] >= MOD) f[t1] -= MOD;
                        //if(f[t2] < 0) f[t2] += MOD;
                    }
                    if (op == 2) {   //and
                        f[t1] = x1 + x2;
                        f[t2] = x2;
                        //if(f[t1] >= MOD) f[t1] -= MOD;
                    }
                    if (op == 3) {   //or
                        f[t1] = x1;
                        f[t2] = x2 + x1;
                        //if(f[t2] >= MOD) f[t2] -= MOD;
                    }
                }
            }
        }
    }
    void ifwt(ll f[], int len, int op) {
        int n = (1 << len);
        for (int i = len; i >= 1; --i) {
            int m = (1 << i), len = m >> 1;
            for (int r = 0; r < n; r += m) {
                int t1 = r, t2 = r + len;
                for (int j = 0; j < len; ++j, ++t1, ++t2) {
                    ll x1 = f[t1], x2 = f[t2];
                    if (op == 1) {   //xor
                        f[t1] = (x1 + x2) / 2;
                        f[t2] = (x1 - x2) / 2;
                        //f[t1] = (x1 + x2) * inv2;
                        //f[t2] = (x1 - x2) * inv2;
                        //if(f[t1] >= MOD) f[t1] %= MOD;
                        //if(f[t2] >= MOD) f[t2] %= MOD;
                        //if(f[t2] < 0) f[t2] = f[t2] % MOD + MOD;
                    }
                    if (op == 2) {   //and
                        f[t1] = x1 - x2;
                        f[t2] = x2;
                        //if(f[t1] < 0) f[t1] += MOD;
                    }
                    if (op == 3) {   //or
                        f[t1] = x1;
                        f[t2] = x2 - x1;
                        //if(f[t2] < 0) f[t2] += MOD;
                    }
                }
            }
        }
    }
    View Code

    中国剩余定理

       互质

    void exgcd(int a,int b,int &x,int &y)
    {
        if (b==0){x=1;y=0;return ;}
        exgcd (b,a%b,x,y);
        int t=x;x=y;y=t-a/b*y;
    }
    int CRT (int a[],int b[],int nn)
    {
    ///a为模数,b为余数,poj1006
        int res=0,x,y;
        for(int i=1;i<=3;i++){
            int as=nn/a[i];
            exgcd(as,a[i],x,y);
            res+=as*x*b[i];
        }
        return res;
    }
    View Code

        不互质(未测试)

    inline LL gcd(LL a,LL b){
        return b?gcd(b,a%b):a;
    }
    inline LL lcm(LL a,LL b){
        return a*b/gcd(a,b);
    }
    inline void exgcd(LL a,LL b,LL &x,LL &y){//a,b,x,y同ax+by=gcd(a,b)中的a,b,x,y
        if(!b){
            x=1,y=0;return;
        }
        LL t;
        exgcd(b,a%b,x,y);
        t=x,x=y,y=t-(a/b)*y;
    }
    inline bool merge(LL a1,LL m1,LL a2,LL m2,LL &a3,LL &m3){
        //将方程x=a1+k1m1和x=a2+k2m2合并为x=a3+k3m3;
        LL d=gcd(m2,m1),a=a2-a1,q,y;
        if(a%d){
            return false;
        }//无解
        m3=lcm(m1,m2);
        exgcd(m1/d,m2/d,q,y);
        a3=a/d*q*m1+a1;
        ((a3%=m3)+=m3)%=m3;
        return true;
    }
    inline LL CRT(LL a[],LL m[],int n){
        ///m为模数
        LL a1=a[1],m1=m[1];
        bool ok;
        for(int i=2;i<=n;i++){
            ok=merge(a1,m1,a[i],m[i],a1,m1);
            if(!ok)break;
        }
        if(!ok)return -1;
        return (a1%m1+m1)%m1;//返回最小正整数解
    }
    View Code

     线性求1~n中所有数%p下的逆元

    void Inv(int p,int a[],int n){
    //线性求<=n的数%p意义下的逆元
        a[1]=1;
        for(int i=2;i<=n;i++){
            a[i]=1LL*(p-p/i)*a[p%i]%p;
        }
    }
    View Code

     莫比乌斯反演

      小红书版

    int mu[1<<20];
    LL n;
    bool check[1<<20];
    int prime[1<<20];
    
    void Moblus()
    {
        memset(check,false,sizeof(check));
        mu[1]=1;
        int tot=0;
        for(int i=2;i<=(1<<20);i++){
            if(!check[i]){
                prime[tot++]=i;
                mu[i]=-1;
            }
            for(int j=0;j<tot;j++){
                if(i*prime[j]>(1<<20)) break;
                check[i*prime[j]]=true;
                if(i%prime[j]==0){
                    mu[i*prime[j]]=0;break;
                }
                else{
                    mu[i*prime[j]]=-mu[i];
                }
            }
        }
    }
    View Code

      hzw大爷版

    int tot;
    int mupre[maxn],mu[maxn],pri[maxn];
    bool mark[maxn];
    void init_mu()
    {
        mu[1]=1;
        for(int i=2;i<=maxn;i++){
            if(!mark[i]){mu[i]=-1;pri[++tot]=i;}
            for(int j=1;j<=tot&&i*pri[j]<=maxn;j++){
                mark[i*pri[j]]=1;
                if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
                else mu[i*pri[j]]=-mu[i];
            }
        }
        for(int i=1;i<=maxn;i++)
            mupre[i]=mupre[i-1]+mu[i];
    }
    View Code

     矩阵快速幂

    ///使用前要先对r,c赋值
    struct mat{
        long long a[30][30];
        int r,c;
        mat operator *(const mat &b)const{
            mat ret;
            for (int i=0;i<r;i++){
                for (int j=0;j<b.c;j++){
                    ret.a[i][j]=0;
                    for (int k=0;k<c;k++)
                        ret.a[i][j]+=a[i][k]*b.a[k][j],ret.a[i][j]%=MOD;
                }
            }
            ret.r=r;
            ret.c=b.c;
            return ret;
        }
        void init_unit(int x)
        {
            r=c=x;
            for(int i=0;i<r;i++){
                for(int j=0;j<c;j++){
                    if(i==j)a[i][j]=1;
                    else a[i][j]=0;
                }
            }
        }
    }unit;
    mat qmod(mat p,LL n){
        unit.init_unit(p.c);
        mat ans=unit;
        while(n){
            if(n&1)ans=p*ans;
            p=p*p;
            n>>=1;
        }
        return ans;
    }
    View Code

    求n!中有多少个m的乘积

    LL solve(LL n,LL p)
    {///返回个数,p为质数
        LL ans=0;
        while(n){
            n=n/p;
            ans+=n;
        }
        return ans;
    }
    View Code
  • 相关阅读:
    Python3 WebDriver操作cookie的方法
    Windows创建定时任务执行Python脚本
    Python3 自定义请求头消息headers
    为什么SQL用UPDATE语句更新时更新行数会多3行有触发器有触发器有触发器有触发器有触发器有触发器
    【C#】C#获取文件夹下的所有文件
    jQuery.ajax()调用asp.net后台方法(非常重要)
    Asp.Net+JQuery.Ajax之$.post
    c# post 接收传来的文件
    C#使用GET、POST请求获取结果,这里以一个简单的用户登陆为例。
    javascript中let和var的区别
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9439053.html
Copyright © 2020-2023  润新知