数论(Mathmatics)总结[1]

Instructions

数学问题纯粹靠感觉啊。。。感觉很多定理都随缘啊。。。。大概总结一下8。

质数

无穷理论的证明:
设质数有有限的n个,依次为p₁,p₂,p₃,…,pn,则令N=p₁p₂p₃pn。
1.若N+1为质数,则N+1一定是一个新的质数
2.若N+1为合数,则N一定存在一个不等于p₁,p₂,p₃,…,pn的质数因子。


质数判定的方法:
1.枚举,范围[2,sqrt(n)]。
2.筛选法(打表预处理)
1)、Eratosthenes筛法:用质数i筛掉i的倍数。
:2i,3i,4i…都是合数,一般从ii开始筛,因为2i已经筛过了,3i被3筛过了。
①效率接近线性
②存在重复筛选的问题(eg:15被3、5都筛了一次)
2)、欧拉线性筛:每个合数只用被最小的质因子筛掉。
①num[i]记录i的最小质因子,如果num[i]==i,则i就是质数。
②接下来从小到大枚举已确定的质数primes[j],则i
primes[j]的最小质因子一定是primes[j],除非primes[j]>num[i]。
O(n)的时间复杂度。
欧拉筛模板:

inline void OULA(){
    for(int i=2;i<=maxn;i++){
        if(!num[i])primes[++cnt]=i;
        for(int j=1;i*primes[j]<=maxn;j++){
            num[i*primes[j]]=true;
            if(i%primes[j]==0)break;
        }
    }
}

约数

N=p1^c1*p2^c2*…*pm^cm。
①N的正约数{p1^b1*p2^b2*…*pm^bm|0<=bi<=ci}。
②N的正约数个数为(c1+1)(c2+1)…(cm+1)=∏i=1~m(ci+1)。
③N的所有正约数和为(1+p1+p1²+…+p1^c1)*…*(1+pm+pm²+…+pm^cm)。

求N的正约数集合:
枚举,1-sqrt(n),完全平方数需要特判。(约数有对称性定理)
对于正整数N,约数上限为2sqrt(n)个。
求1-N中所有数字的正约数:枚举时间复杂度O(N
sqrt(N))。
可以像Eratosthenes筛质数一样,i一定是i的倍数的约数,时间复杂度近似O(nlogn)。

欧拉筛+欧拉函数phi模板:

inline void OULA(){
    for(int i=2;i<=maxn;i++){
        if(!num[i]){
            primes[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;i*primes[j]<=maxn;j++){
            num[i*primes[j]]=true;
            phi[i*primes[j]]=phi[i]*(primes[j]-1);
            if(i%primes[j]==0){
                phi[i*primes[j]]=phi[i]*primes[j];
                break;
            }
        }
    }
}

直接求phi模板:

inline int phii(int x){
    ans3=n;
    for(int i=2;i<=sqrt(n+1);i++){
        if(x%i==0){
            ans3=ans3*(i-1)/i;
            while(x%i==0){
                x/=i;
            }
        }
    }
    if(x>1){
        ans3=ans3*(x-1)/x;
    }
}

试除法求约数模板:

inline void Factor(int x){
    for(int i=1;i<=sqrt(x+1);i++){
        if(x%i==0){
            ans[++cntt]=i;
            if(i!=x/i)ans[++cntt]=x/i;
        }
    }
    sort(ans+1,ans+cntt+1);
    for(int i=1;i<=cntt;i++){
        printf(" %lld",ans[i]);
        ans2+=ans[i];
    }
    printf("
");
}

整数唯一分解:
a=p1e1*p2e2p3e3*…*pnen(p1<p2<…<pn);
b=p1f1*p2f2
p3f3*…*pnfn。
则gcd(a,b)=p1min(e1,f1)*p2min(e2,f2)pn^min(en,fn);
lcm(a,b)=p1max(e1,f1)*p2max(e2,f2)pn^max(en,fn)。
其因数个数为(e1+1)(e2+1)…(en+1)。

inline void workk(int x){
	vector<int>a;
	vector<int>b;
	int k=0;
	for(int i=2;i<=sqrt(x+1);i++){
		if(x%i==0){
			k=0;
			a.push_back(i);
			while(x%i==0){
				x/=i;
				k++;
			}
			b.push_back(k);
		}
	}
	if(x>1){
		a.push_back(x);
		b.push_back(1);
	}
	printf("%d=",n);
	for(int i=0;i<a.size();i++){
		printf("%d^%d",a[i],b[i]);
		if(i+1!=a.size())printf("*");
	}
	printf("
");
}

矩阵

矩阵快速幂模板:

inline void Mull(){
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=k;i++){
        for(int j=1;j<=k;j++){
            long long val=0;
            for(int q=1;q<=k;q++){
                val+=(ret[i][q]%m*a[q][j]%m)%m;
            }
            ans[i][j]=val%m;
        }
    }
    for(int i=1;i<=k;i++){
        for(int j=1;j<=k;j++){
            ret[i][j]=ans[i][j];
        }
    }
}
inline void Mull_Self(){
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=k;i++){
        for(int j=1;j<=k;j++){
            long long val=0;
            for(int q=1;q<=k;q++){
                val+=(a[i][q]%m*a[q][j]%m)%m;
            }
            ans[i][j]=val%m;
        }
    }
    for(int i=1;i<=k;i++){
        for(int j=1;j<=k;j++){
            a[i][j]=ans[i][j];
        }
    }
}
inline void Quick_Pow(long long x){
    memset(ret,0,sizeof(ret));
    for(int i=1;i<=k;i++){
        ret[i][i]=1;
    }
    while(x){
        if(x&1)Mull();
        Mull_Self();
        x>>=1;
    }
}

快速幂优化递推例题链接:递推的矩阵优化

莫比乌斯反演

对于f(x),可以很方便得到∑d|nf(d),即:F(n)=∑d|nf(d)。
两个重要的反演公式:
1.F(n)=sigma n|k(f(k)) -->f(n)=sigma n|k(Mo[k/n]F(k))
2.F(n)=sigma k|n(f(k)) -->f(n)=sigma k|n(Mo[k]
F(n/k))
莫比乌斯(Möbius)函数:
①μ(d)=1,d=1;
②μ(d)=(-1)ⁿ,d=p₁p₂p₃…pn;
③μ(d)=0,d=others。(存在pn²质因子)
莫比乌斯函数预处理模板:

inline void Mobius(){
    Mo[1]=1;
    for(int i=2;i<=maxn-1;i++){
        if(!num[i]){
            primes[++cnt]=i;
            Mo[i]=-1;
        }
        for(int j=1;j<=cnt&&i*primes[j]<maxn;j++){
            num[i*primes[j]]=true;
            Mo[i*primes[j]]=Mo[i]*(-1);
            if(i%primes[j]==0){
                Mo[i*primes[j]]=0;
                break;
            }
        }
    }
}

例题:HAOI2011

卡特兰数

例题:NOIP普及组2003

原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10331081.html