分圆多项式整理

前言

在你谷上面找到一个分圆多项式的板子题,然后扒下来把分圆多项式又复习了一遍。

鸣谢:

本原单位根

要讲分圆多项式肯定要先讲本原单位根。

与本原毕达哥拉斯三元组一样,本原单位根显然有 \(\gcd(i,j)=1\) 这样类型的限制。那么映射到单位根这里,是指 \(\omega_n^k\) 中有 \(\gcd(n,k)=1\)

那么我们得到 \(n\) 次的本原单位根有 \(\varphi(n)\) 个。

分圆多项式

定义一个 \(n\) 次的分圆多项式 \(\Phi_n(x)\)。我们有他的 \(\varphi(n)\) 个本原单位根,假设为 \(\epsilon_1,\epsilon_2,\epsilon_3,...,\epsilon_{\varphi(n)}\)。那么此时 \(\Phi_n(x)=\prod_{i=1}^n(x-\epsilon_d)\)

根据这个定义可以写出:

\[\Phi_n(x)=\prod_{k=1}^n(x-\omega_n^k)^{[\gcd(n,k)=1]} \]

性质

性质 1

\[\prod_{d|n}\Phi_d(x)=x^n-1 \]

要证两个首一多项式相等,可以证明 \(\prod_{d|n}\Phi_d(x)|x^n-1\),且 \(x^n-1|\prod_{d|n}\Phi_d(x)\)。此处证明略,留作思考。

例:P1250 - 因式分解

分解 \(x^n-1\),运用分圆多项式的这个性质,就可以将其转化为求解 \(\Phi_d(x)\) 的问题。

性质 2

\[\Phi_d(x)=\prod_{d|n}(x^d-1)^{\mu(\frac{n}{d})} \]

pf: 因为 \(\prod_{d|n}\Phi_d(x)=x^n-1\),对两边同时去对数,得:

\[\ln(\prod_{d|n}\Phi_d(x))=\ln(x^n-1) \]

展开,并进行莫比乌斯反演得:

\[\ln(\Phi_n(x))=\sum_{d|n}\ln(x^d-1)\mu(\frac{n}{d}) \]

两边同时 \(\exp\)

\[\Phi_n(x)=\prod_{d|n}(x^d-1)^{\mu(\frac{n}{d})} \]

Q.E.D。

继续回到上面看 P1520 因式分解。按照这个式子模拟一下即可。

参考了一下鱼的。

#include<bits/stdc++.h>
#define HohleFeuerwerke using namespace std
#pragma GCC optimize(3,"Ofast","-funroll-loops","-fdelete-null-pointer-checks")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#define int long long
HohleFeuerwerke;
inline int read(){
	int s=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) s=s*10+c-'0';
	return s*f;
}
inline void write(int x){
	if(x<0) putchar('-'),x=-x;
	if(x>=10) write(x/10);
	putchar('0'+x%10);
}
const int MAXN=6e3+5,MAXNlog2=1e2+5;
int mu[MAXN],pri[MAXN],tot;
bool ispri[MAXN];
inline void init(){
	mu[1]=ispri[1]=true;
	for(int i=2;i<=MAXN-5;i++){
		if(!ispri[i]) pri[++tot]=i,mu[i]=-1;
		for(int j=1;j<=tot&&i*pri[j]<=MAXN-5;j++){
			ispri[i*pri[j]]=true;
			if(i%pri[j]) mu[i*pri[j]]=-mu[i];
			else{mu[i*pri[j]]=0;break;}
		}
	}
}
struct poly{
	int len,a[MAXN];
	poly(){memset(a,0,sizeof(a));len=0;}
	inline int operator [](const int &x)const{return a[x];}
	inline int& operator [](const int &x){return a[x];}
}phi[MAXNlog2];
inline void print(poly x){
	for(int i=x.len;i>=0;i--){
		if(i==1&&i==x.len){
			if(x[i]>0&&x[i]!=1) printf("%lldx",x[i]);
			if(x[i]==1) printf("x");
			if(x[i]<0&&x[i]!=-1) printf("%lldx",x[i]);
			if(x[i]==-1) printf("-x");
		}
		else if(i==x.len){
			if(x[i]==1) printf("x^%lld",i);
			else printf("%lldx^lld",x[i],i);
		}
		else if(i==1){
			if(x[i]>0&&x[i]!=1) printf("+%lldx",x[i]);
			if(x[i]==1) printf("+x");
			if(x[i]<0&&x[i]!=-1) printf("%lldx",x[i]);
			if(x[i]==-1) printf("-x");
		}
		else if(i==0){
			if(x[i]>0) printf("+%lld",x[i]);
			else printf("%lld",x[i]);
		}
		else{
			if(abs(x[i])!=1){
				if(x[i]<0) printf("-%lldx^%lld",abs(x[i]),i);
				if(x[i]==0) continue;
				if(x[i]>0) printf("+%lldx^%lld",x[i],i);
			}
			if(abs(x[i])==1){
				if(x[i]==-1) printf("-x^%lld",i);
				if(x[i]==1) printf("+x^%lld",i);
			}
		}
	}
}
inline void multi(poly &f,int d){
        f.len+=d;
        for(int i=f.len;i>=d;i--) f[i]=f[i-d]-f[i];
        for(int i=0;i!=d;i++) f[i]=-f[i];
}
inline bool cmp(poly a,poly b){
        if(a.len!=b.len) return a.len<b.len;
        for(int i=a.len;i>=0;i--){
                if(abs(a[i])!=abs(b[i])) return abs(a[i])<abs(b[i]);
                if(a[i]!=b[i]) return a[i]<b[i];
        }
        return true;
}
inline poly getphi(int n){
	poly mul,div,ret;
        mul[0]=div[0]=1;
        for(int d=1;d*d<=n;++d){
                if(n%d!=0) continue;
                if(mu[n/d]==1) multi(mul,d);
                else if(mu[n/d]==-1) multi(div,d);
                if(d*d==n) continue;
                if(mu[d]==1) multi(mul,n/d);
                else if(mu[d]==-1) multi(div,n/d);
        }
        if(div.len==0) return mul;
        ret.len=mul.len-div.len;
        ret[0]=mul[0]*div[0];
        for(int i=1;i<=ret.len;i++){
                ret[i]=mul[i];
                for(int j=0;j!=i;j++) ret[i]-=ret[j]*div[i-j];
                ret[i]*=div[0];
        }
        return ret;
}
int n,polycnt;
signed main()
{
//	freopen("P1520_2.in","r",stdin);
//	freopen("P1520_2-mine.out","w",stdout);
	n=read();
        init();
        for(int i=1;i<=sqrt(n);++i){
                if(n%i!=0) continue;
                phi[++polycnt]=getphi(i);
                if(i!=sqrt(n)) phi[++polycnt]=getphi(n/i);
        }
        if(polycnt==1){
                print(phi[1]);
                return 0;
        }
        sort(phi+1,phi+1+polycnt,cmp);
        for(int i=1;i<=polycnt;++i){
    	        printf("("),print(phi[i]),printf(")"); 
        }
        puts("");
        return 0;   
}

性质三

分圆多项式在 \(\mathbb{Q}\) 内不可约。可以运用爱森斯坦判别法证明。

拓展:爱森斯坦判别法是指:对一个整系数多项式 \(f(x)=\sum_{i=0}^na_ix^i\),如果存在素数 \(p\),使得:

  1. \(p\not|a_n\)\(p|a_0,a_1,a_2,a_3,...,a_{n-1}\)
  2. \(p^2|a_0\)

那么 \(f(x)\)\(\mathbb{Q}\) 上不可约。

性质四

已知 \(n\) 是大于 \(1\) 的正整数,且 \(n\not=6\),则当 \(x\leq2\) 时,恒有 \(\Phi_n(x)>n\)

性质五

\(a,n\) 都是正整数,\(a>1,n>2\)\(p\) 是素数,\(p|\gcd(n,\Phi_n(a))\),则 \(p\)\(n\) 的最大素因子,且 \(p^2\not|\Phi_n(a)\)

与数论的联系

莫比乌斯函数

可以看出,在导出分圆多项式的时候运用了莫比乌斯反演。那么显然,单位根有与莫比乌斯函数相关的推论。

\[\mu(k)=\sum_{k=1,\gcd(k,n)=1}^n\omega_n^k \]

Zisgmondy's Theorem(席格蒙德定理)

若有 \(a,b\in\mathbb{N}^{+}\)\(\gcd(a,b)=1\)\(a>b\)\(n\in\mathbb{N}^{+},n>1\)。则:

  • i. 存在 \(a^n-b^n\) 的一个素因子 \(p\),使得对任意小于 \(n\) 的正整数 \(k\),都有 \(p\) 不整除 \(a^k-b^k\)。以下两情形除外:
    • \(n=2\) 时,\(a+b\)\(2\) 的幂。
    • \(n=6\) 时,\(a=2,b=1\)
  • ii. 存在 \(a^n+b^n\) 的一个素因子 \(q\),使得对任意小于 \(n\) 的正整数 \(k\),都有 \(q\) 不整除 \(a^k+b^k\)\(a=2,b=1,n=3\) 时除外。

Zisgmondy's Theorem 当 \(b=1\) 时,Part 1 就会变成:\(a>1,a\in\mathbb{N}^{+}\)\(n>2,n\not=6,n\in\mathbb{N}^{+}\),那么存在素数 \(p\),满足:

  • i. \(p|a^n-1\)
  • ii. 对于任意 \(m\in\mathbb{N}^{+},m<n\),都有 \(p|a^m-1\)
    这个是可以用分圆多项式来导出的。

结语

分圆多项式和很多高代和数论内容相关,可以说是一座连接数论和代数的重要桥梁。本文中介绍的性质不过冰山一角,留待更多美妙优雅之处等待读者自行探寻。

posted @ 2020-08-17 16:39  _HofFen  阅读(2326)  评论(0编辑  收藏  举报