zoukankan      html  css  js  c++  java
  • 【模板】数论

    公约数
    gcd

    LL gcd(LL a,LL b){
        return b==0? a:gcd(b,a%b);
    }
    

    ex_gcd

    //返回值为最大公约数
    LL ex_gcd(LL a,LL b,LL &x,LL &y){
        LL d = a;
        if(!b){x = 1,y = 0;}
        else{
          d = ex_gcd(b,a%b,y,x);
          y-=a/b*x;
        }
        return d;
    }
    

    素数

    素因子分解

    线性筛

    void xxs(){
        int tot = 0;
        memset(check, 0, sizeof(check));
        for (int i = 2; i < MAXL; ++i){
            if (!check[i]){
                prime[tot++] = i;
            }
            for (int j = 0; j < tot; ++j){
                if (i * prime[j] > MAXL) break;
        	    check[i*prime[j]] = 1;
         	    if (i % prime[j] == 0) break;
        }
    }
    

    朴素算法(O(sqrt n))

    void prime_factor(int n,map<int,int> &pf){
        for(int i =2 ; i*i<=n ; ++i){//n为素数时!
            while(n%i==0){
                ++pf[i];
                n/=i;
            }
        }
        if(n!=1)pf[n] = 1;
    }
    

    Eratosthenes筛法

    void Eratosthenes(int n){
        memset(is_prime,true,sizeof(is_prime));
    
        for(int i = 2 ; i*i<=n; ++i)
            if(is_prime[i])
            for(int j=i*i ; j<=n ; j+=i)is_prime[j] = false;
    }
    

    区间筛法

    void segment_sieve(LL a,LL b){//[a,b]
        memset(is_prime_ab,true,sizeof(is_prime_ab[0])*(b-a+1));
        memset(is_prime_sqrtb,true,sizeof(is_prime_sqrtb[0])*(sqrt(b)+2));
        for(LL i = 2 ; i*i<=b ; ++i)
        if(is_prime_sqrtb[i]){
            for( LL j = i*i ; j*j<=b ; j+=i)is_prime_sqrtb[j] = false;
            for(LL j = max(i*i,(a-1)/i+1)*i ; j<=b ; j+=i)is_prime_ab[j-a] = false;
        }
    }
    

    大素数分解与大素数测试

    miller_rabin

    已知最快的素数分解算法.(O(lgV))

    bool witness(LL a,LL n,LL u,LL t){
    	LL x0 = power_mod(a,u,n),x1;
    	for(int i=1 ;i<=t ; ++i){
    		x1 = mulmod(x0,x0,n);
    		if(x1==1 && x0!=1 && x0!=n-1)
    			return false;
    		x0 = x1;
    	}
    	if(x1 !=1)return false;
    	return true;
    }
    
    bool miller_rabin(LL n, int times = 20){
    	if(n<2)return false;
    	if(n==2)return true;
    	if(!(n&1))return false;
    	LL u = n-1,t =0;
    	while (u%2==0) {
    		t++;u>>=1;
    	}
    	while (times--) {
    		LL a = random(1,n-1);
    		//if(a == 0)std::cout << a << " "<<n<< " "<<u<<" " << t<<'
    ';
    		if(!witness(a,n,u,t))return false;
    	}
    	return true;
    }
    

    pollard_rho 分解一个合数(V)的运行时间(O(V^{1/4 }))

    /*
    *pollard_rho分解n,
    *c : 随机迭代器,每次运行设置为随机种子往往更快.
    */
    LL pollard_rho(LL n,LL c = 1){
    	LL x  = random(1,n);
    	LL i =1,k =2,y = x;
    	while (1) {
    		i++;
    		x = (mulmod(x,x,n)+c)%n;
    		LL d = gcd(y-x>=0?y-x:x-y,n);
    		if(d!=1 && d!=n)return d;//非平凡因子.
    		if(y==x)return n;//重复.
    		if(i==k){ y = x ; k<<=1;}//将x_1,2,4,8,16,..赋值为y.
    	}
    }
    
    找出因子分解 $O(V^{1/4}lgV)$
    
    void find_factor(LL n,std::map<LL, int>  & m){
    	if(n<=1)return ;
    	if(miller_rabin(n)){
    		++m[n];
    		return ;
    	}
    	LL p = n;
    
    	while (p==n)p = pollard_rho(p,random(1,n));
    	find_factor(p,m);
    	find_factor(n/p,m);
    }
    

    euler phi函数

    [phi(n) = nprod_{i = 1}^{k}(1-frac{1}{p_i}) ]

    证明详见《初等数论及其应用》

    int  euler_phi(int  n){
        int  ans = n;
        for(int i=2 ; i*i<=n ; ++i)
            if(ans%i ==0)
            {
                ans = ans/i*(i-1);
                while(n%i==0)n/=i;
            }
            if(n>1)ans = ans/n*(n-1);
        return ans;
    }
    

    phi_table,类似于线性筛的做法

    void phi_table(int n){
        memset(phi,0,sizeof(phi[0])*(n+5));
        phi[1] = 1;
        for(int i = 2 ; i<=n ; ++i){
            if(!phi[i]){//素数标记
                for(int j = i ; j<=n ; j+=i){
                    if(!phi[j])phi[j] = j;
                    phi[j] = phi[j]/i*(i-1);
                }
            }
        }
    }
    

    模运算
    power_mod

    LL power_mod(LL x,LL n,LL mod){
        LL res = 1;
        while(n){
            if(n&1)res = (res*x)%mod;
            x = (x*x)%mod;
            n>>=1;
        }
        return res;
    }
    

    大数乘法取模

    LL mulmod(LL a,LL b,LL mod){
    	LL res =0,y = a%mod;
    	while (b) {
    		if(b&1)res = (res+y)%mod;
    		b>>=1;
    		y = (y<<1)%mod;
    	}
    	return res;
    }
    

    大整数取模

    LL big_mod(string val,LL mod){
        LL res = 0;
        for(int i=0 ; i<val.length() ; ++i){
            res = ((res)*10+val[i]-'0')%mod;
        }
        return res;
    }
    

    模方程

    LL MLE(LL a,LL b,LL n){
        LL d,x,y;
        d = ex_gcd(a,n,x,y);
        if(b%d !=0){
            return -1;
        }else{
            LL x0 = x*b/d%n+n;
            return x0%(n/d);//模(n/d)
        }
    }
    

    乘法逆元 a在模n意义下的逆

    LL inv(LL a,LL n){
        LL x,y;
        LL d = ex_gcd(a,n,x,y);
        return d==1? (x+n)%n:-1;//非负性保证.
    }
    

    中国剩余定理

    //x % m[i] = a[i]
    LL china(int n,int *a,int *m){
        LL M = 1,x = 0,y,z;
        for(int i=0 ; i<n ; ++i)M*=m[i];
        for(int i=0 ; i<n ; ++i){
            LL M_i = M/m[i];
            ex_gcd(M_i,m[i],y,z);//M_i*y = 1(mod m[i])
            x = (x+M_i*a[i]*y)%M;
        }
        return (x+M)%M;
    }
    

    朴素模方程((m_i不两两互素的时候))

    LL MLE(int *r,int *mod,int n){
    	LL lm = 0, lb = 1;
    	for (int i = 0; i < n; i++)
    	{
    		LL k1,k2;
    		LL d= exgcd(lb, mod[i],k1,k2);	// x=c1(mod r1)
    		if ((lm - r[i]) % d) { return -1; }	// 联立x=r2(mod m2),(r1-r2)=0(mod gcd)才有解
    		lb = lb / d * mod[i];							// lcm
    		LL z = k2 * ((lm - r[i]) / d);						// 求出k2
    		lm = z * mod[i] + r[i];											// 得到方程组的一个最小解
    		lm = ((lm % lb) + lb) % lb;										// 保证最小解大于0
    	}
    	return lm;
    }
    

    莫比乌斯反演 线性筛法(O(n))

    int prime[maxn],cnt;
    int mu[maxn];
    
    void init_mobius(){
        memset(prime,0,sizeof(prime));
        mu[1] =1;
        cnt =0;
        for(int i=2 ;i<maxn ; ++i){
            if(!prime[i]){
                prime[cnt++] = i;
                mu[i] = -1;
            }
            for(int j=0 ; j<cnt && i*prime[j]<maxn ; ++j){
                prime[i*prime[j]] = 1;
                if(i%prime[j])mu[i*prime[j]] = -mu[i];
                else {
                    mu[i*prime[j]] = 0;
                    break;
                }
            }
        }
    }
    
  • 相关阅读:
    Centos7.3安装jdk和maven
    Centos7.3安装sftp服务和ssh
    Centos7.3安装,并设置网络和防火墙
    Docker 常用命令
    Tomcat配置
    MySQL配置
    配置JDK
    JTable的模型
    JavaBean和List<JavaBean>
    JavaBean
  • 原文地址:https://www.cnblogs.com/hanser/p/7692615.html
Copyright © 2011-2022 走看看