题解 P1520 【因式分解】
NaCly_Fish · · 题解
已重制,尽可能兼顾浅显易懂与严谨性地说明这题。
思路
我们要对
也就是说:
如果能对这
分圆多项式
方便后面表述,这里定义:对于复数
定义分圆多项式
(即它是由所有
对于任意
使用这种方法来分配
然后你可能会问,
将等式两边取对数,得
看到这个形式想到什么?没错,就是 mobius 反演。
再
如果想了解相关证明,还请继续往下阅读。
整系数的证明
先来证明个简单的:
不妨考虑将
显然
引入:最小多项式
证明
对于一个代数数
\alpha ,能满足f(\alpha)=0 的、非常数的、首项为1 且次数最低的多项式称为「最小多项式」。
最小多项式有三大性质:「不可约性」、「唯一性」,以及任意以
不可约性的证明
现在让我们开始吧!
考虑反证法,假设
然后选取
值得说明的是:固定
找出
如果
所以只能是
进一步地,根据
现在我们将问题转移到有限域
在
如此展开下去计算即可证明。
然后对于整系数多项式
现在我们知道,
最后,我们发现
即,
计算细节
最后是一些计算上的细节,求
参考代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 10003
#define ll long long
#define p 998244353
using namespace std;
int mu[N],pr[N>>1];
bool vis[N];
struct poly{
int a[N];
int t;
inline poly(int t=0):t(t){ memset(a,0,sizeof(a)); }
inline int operator [] (const int& x) const{ return a[x]; }
inline int& operator [] (const int& x){ return a[x]; }
inline bool operator < (const poly& b) const{
if(t!=b.t) return t < b.t;
for(int i=t;~i;--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 void print(){
if(abs(a[t])!=1) printf("%dx^%d",a[t],t);
else{
if(t==1) putchar('x');
else printf("x^%d",t);
}
for(int i=t-1;i;--i){
if(a[i]==0) continue;
if(a[i]>0) putchar('+');
else putchar('-');
if(abs(a[i])!=1) printf("%dx",abs(a[i]));
else putchar('x');
if(i!=1) printf("^%d",i);
}
printf(a[0]>0?"+1":"-1");
}
}phi[73];
void sieve(int n){
int cnt = 0;
mu[1] = 1;
for(int i=2;i<=n;++i){
if(!vis[i]){
pr[++cnt] = i;
mu[i] = -1;
}
for(int j=1;j<=cnt&&i*pr[j]<=n;++j){
vis[i*pr[j]] = true;
if(i%pr[j]==0){
mu[i*pr[j]] = 0;
break;
}
mu[i*pr[j]] = -mu[i];
}
}
}
inline void multiply(poly &f,int d){
f.t += d;
for(int i=f.t;i>=d;--i) f[i] = f[i-d]-f[i];
for(int i=0;i!=d;++i) f[i] = -f[i];
}
inline poly getphi(int n){
static poly mul,div,res;
mul = div = poly();
mul[0] = div[0] = 1;
for(int d=1;d*d<=n;++d){
if(n%d!=0) continue;
if(mu[n/d]==1) multiply(mul,d);
else if(mu[n/d]==-1) multiply(div,d);
if(d*d==n) continue;
if(mu[d]==1) multiply(mul,n/d);
else if(mu[d]==-1) multiply(div,n/d);
}
if(div.t==0) return mul;
res.t = mul.t-div.t;
res[0] = mul[0]*div[0];
for(int i=1;i<=res.t;++i){
res[i] = mul[i];
for(int j=0;j!=i;++j) res[i] -= res[j]*div[i-j];
res[i] *= div[0];
}
return res;
}
int n,fc;
int main(){
scanf("%d",&n);
sieve(n);
for(int i=1;i*i<=n;++i){
if(n%i!=0) continue;
phi[++fc] = getphi(i);
if(i*i!=n) phi[++fc] = getphi(n/i);
}
if(fc==1){
phi[1].print();
return 0;
}
sort(phi+1,phi+1+fc);
for(int i=1;i<=fc;++i){
putchar('(');
phi[i].print();
putchar(')');
}
return 0;
}