自用数论板子

bool vis[MAXN];
ll prime[MAXN],cnt;//素数个数;
ll mu[MAXN],mus[MAXN];
void getMus(){//线性筛求莫比乌斯函数1-N的函数值 
    int N=MAXN;
    //memset(mu,0,sizeof(mu));
    memset(vis,0,sizeof(vis));
    mu[1] = 1;
    cnt = 0;
    for(ll i=2; i<=N; ++i){
        if(!vis[i]){prime[++cnt] = i;mu[i] = -1;}
        for(int j=1;j<=cnt&&i*prime[j]<=N;++j){
            vis[i*prime[j]] = 1;
            if(i%prime[j]) mu[i*prime[j]] = -mu[i];
            else{
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
    for(int i=1;i<=N;i++)mus[i]=mus[i-1]+mu[i];
}
 
ll phi[MAXN],phis[MAXN];
void getPhis(){//线性筛求欧拉函数1-N的函数值 
    int N=MAXN;
    //memset(phi,0,sizeof(phi));
    memset(vis,0,sizeof(vis));
    phi[1] = 1;
    cnt = 0;
    for(ll i=2; i<=N; ++i){
        if(!vis[i]){prime[++cnt] = i;phi[i] = i-1;}
        for(int j=1;j<=cnt&&i*prime[j]<=N;++j){
            vis[i*prime[j]] = 1;
            if(i%prime[j]) phi[i*prime[j]] = phi[i]*(prime[j]-1);
            else{
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
        }
    }
    for(int i=1;i<=N;i++)phis[i]=phis[i-1]+phi[i];
}
 
void phimu(){//同时求莫比乌斯与欧拉函数值 
	int N=MAXN;
	memset(phi,-1,sizeof(phi));
	memset(mu,-1,sizeof(mu));
	cnt=0;
	phi[0]=mu[0]=0;phi[1]=mu[1]=1;
	for(ll i=2;i<=N;++i){
		if(phi[i]<0){
			prime[++cnt]=i;
			phi[i]=i-1;//质数的欧拉函数值为p-1 
			mu[i]=-1;//质数的莫比乌斯函数值为-1 
		}
		for(ll j=1;j<=cnt&&i*prime[j]<=N;++j){
			if(i%prime[j]){
				phi[i*prime[j]] = phi[i]*(prime[j]-1);
				mu[i*prime[j]] = -mu[i];
			}
			else {
				phi[i*prime[j]] = phi[i]*prime[j];
				mu[i*prime[j]] = 0;
				break;
			}
		}
	}
	for(ll i=1;i<=N;i++){
		phis[i]=phis[i-1]+phi[i];
		mus[i]=mus[i-1]+mu[i];
	}
}
 
ll v[MAXN];
void primes(long long n){//线性筛打素数表 
	memset(v,0,sizeof(v));
	cnt=0;
	for(ll i=2;i<=n;++i){
		if(v[i]==0){v[i]=i;prime[++cnt]=i;}//v[i]记录i自身的最小因子 
		for(int j=1;j<=cnt;++j){
			if(prime[j]>v[i]||prime[j]>n/i)break;//i有比prime[j]更小的质因子,或者超出范围,停止循环 
			v[i*prime[j]]=prime[j];//prime[j]是合数i*prime[j]的最小因子 
		}
	}
}
 
int getMu(long long n){//筛法求大数(>1e7)单点莫比乌斯函数值 
	long long N=10000000;
	
	if(n<=N)return mu[n];
	int k=1;
	for(long long i=2;i*i<=n;i++){
		if(n%i==0){
			if(n%(i*i)==0)return 0;
			k*=-1,n/=i;
		}
	}
	if(n>1)k*=-1;
	return k;
}
 
long long getPhi(long long n){//求n欧拉函数值 单个点 
	long long ans=n;
	for(ll i=2;i*i<=n;++i)//O(n)算法 
		if(n%i==0){
			ans=ans/i*(i-1);//ans=ans-ans/n;
			while(n%i==0)n/=i;
		}
	if(n>1)ans=ans/n*(n-1);//ans=ans-ans/n;
	return ans;	
}
 
long long getPhi(long long n){//已有素数表快速求n欧拉函数值 单个点 
	long long ans=1;
	for(ll i=1;i<=cnt&&prime[i]*prime[i]<=n;i++){
		if(n%prime[i]==0){
			ans*=(prime[i]-1);
			n=n/prime[i];
			while(n%prime[i]==0){
				ans*=prime[i];
				n/=prime[i];
			}
		}
	}
	if(n>1)ans*=n-1;
	return ans;
}
 
long long slowmul(long long a,long long b ,long long m){//慢速乘法取模 a*b%m
	a%=m;
	long long k=0;
	while(b){
		if(b&1){
			k=k+a;
			if(k>=m)k=k-m;
		}
		a=a<<1;
		if(a>=m)a=a-m;
		b=b>>1;
	}
	return k;
}
 
long long quickpowmod(long long a,long long b ,long long m){//快速幂取模 a^b%m
     long long k=1L;a%=m;
     while(b>0){
        if(b&1)k=slowmul(k,a,m);//如果会超ll 使用慢速乘 
        b=b>>1;
        a=slowmul(a,a,m);//如果会超ll 使用慢速乘 
     }
     return k;
}
 
vector factor;
void factors(ll n){//试除法求n的约数集合 
	factor.clear();
	for(ll i=1;i*i<=n;++i){
		if(n%i==0){
			factor.push_back(i);
			if(i!=n/i)factor.push_back(n/i);
		}
	}
}
 
//整除分块模板
for(int l=1,r;l<=n;l=r+1)
{
    r=n/(n/l);
    ans+=(r-l+1)*cal(n/l);
}
 
//杜教筛模板   
map _phi;
long long CalcPhi(long long n){
	map::iterator ite;
	if(nsecond;
	long long last, ans = n * (n + 1) >> 1;//注意爆longlong 与分数取模
	for(long long i = 2; i <= n; i = last + 1) {
		last = n / (n / i);
		ans -= (last - i + 1) * CalcPhi(n / i);
	}
	return _phi[n] = ans;//记忆化 
}
 
map _mu;
long long CalcuMu(long long n){
	map::iterator ite;
	if(nsecond;
	long long last, ans = 1;
	for(long long i = 2; i <= n; i = last + 1) {
		last = n / (n / i);
		ans -= (last - i + 1) * CalcuMu(n / i);
	}
	return _mu[n] = ans;//记忆化 
}

米勒罗宾素性测试

// 18位素数:154590409516822759
// 19位素数:2305843009213693951 (梅森素数)
// 19位素数:4384957924686954497
long long prime[6] = {2, 3, 5, 233, 331};
long long qmul(long long x, long long y, long long mod) { // 乘法防止溢出, 如果p * p不爆long long的话可以直接乘; O(1)乘法或者转化成二进制加法
    return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
    /*
	long long ret = 0;
	while(y) {
		if(y & 1)
			ret = (ret + x) % mod;
		x = x * 2 % mod;
		y >>= 1;
	}
	return ret;
	*/
}

long long qpow(long long a, long long n, long long mod) {
    long long ret = 1;
    while(n) {
        if(n & 1) ret = qmul(ret, a, mod);
        a = qmul(a, a, mod);
        n >>= 1;
    }
    return ret;
}

bool Miller_Rabin(long long p) {
    if(p < 2) return 0;
    if(p != 2 && p % 2 == 0) return 0;
    long long s = p - 1;
    while(! (s & 1)) s >>= 1;
    for(int i = 0; i < 5; ++i) {
        if(p == prime[i]) return 1;
        long long t = s, m = qpow(prime[i], s, p);
        while(t != p - 1 && m != 1 && m != p - 1) {
            m = qmul(m, m, p);
            t <<= 1;
        }
        if(m != p - 1 && !(t & 1)) return 0;
    }
    return 1;
}

大素数判定和素因子分解(转自kuangbin)

https://www.cnblogs.com/kuangbin/archive/2012/08/19/2646396.html

#include
#include
#include
#include
#include
#include
using namespace std;

//****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小

//计算 (a*b)%c.   a,b都是long long的数,直接相乘可能溢出的
//  a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
    a%=c;
    b%=c;
    long long ret=0;
    while(b)
    {
        if(b&1){ret+=a;ret%=c;}
        a<<=1;
        if(a>=c)a%=c;
        b>>=1;
    }
    return ret;
}

//计算  x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
    if(n==1)return x%mod;
    x%=mod;
    long long tmp=x;
    long long ret=1;
    while(n)
    {
        if(n&1) ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1;
    }
    return ret;
}

//以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
    long long ret=pow_mod(a,x,n);
    long long last=ret;
    for(int i=1;i<=t;i++)
    {
        ret=mult_mod(ret,ret,n);
        if(ret==1&&last!=1&&last!=n-1) return true;//合数
        last=ret;
    }
    if(ret!=1) return true;
    return false;
}

// Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false;
bool Miller_Rabin(long long n)
{
    if(n<2)return false;
    if(n==2)return true;
    if((n&1)==0) return false;//偶数
    long long x=n-1;
    long long t=0;
    while((x&1)==0){x>>=1;t++;}
    for(int i=0;i=n)p=Pollard_rho(p,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p);
}

int main()
{
    long long n;
    while(scanf("%I64d",&n)!=EOF)
    {
        tol=0;
        findfac(n);
        for(int i=0;i

 

你可能感兴趣的:(自用数论板子)