[hdu 6352] Call It What You Want
题意
给出若干组询问,每次询问一个n,求将xn−1分解为分圆多项式的乘积。
具体的,即
xn−1=∏d|nΦd(x)
其中分圆多项式的定义为
Φn(x)=∏1≤k≤n,(n,k)=1(x−wkn)(wn=cos2πn+isin2πn)
(换句话说,让你求出一些分圆多项式)
题解
设f(n)=xn−1,g(d)=Φd(x),已知
f(n)=∏d|ng(d)
通过莫比乌斯反演,可以得到
g(n)=∏d|nf(d)μ(nd)=∏d|nf(nd)μ(d)
注意到我们只需要μ(d)不为0的d,且满足的d都无平方质因子。
注意到d≤n≤105<2×3×5×7×11×13×17,我们只要用26枚举每个有用的d即可。那么因子d对g(n)的贡献项为(1−xnd)μ(d)。
如果用多项式乘法把他们搞起来当然不行,复杂度爆炸。
我考虑这个多项式只有两项有值,可以通过一个巧妙的dp(递推)进行计算。
具体来说,
如果乘上的是(1−xk)1,可以直接用递推来更新系数(本质是01背包);
如果乘上的是(1−xk)−1,亦即(1+xk+x2k+...),可以用类似无限背包的递推来累加系数。
由于Φd(x)的次数是ϕ(d),那么这个部分只需要用O(ϕ(d))的复杂度计算即可。
则总复杂度为O(∑d|n2ω(d)ϕ(d))=O(n26)。
由于数据保证∑n≤5⋅106,所以总复杂度大概是O(5⋅106⋅26)。
#include <bits/stdc++.h>
using namespace std;
inline int read () {
static int x;
scanf("%d", &x);
return x;
}
const int N = 1e5 + 5;
int n, m;
int phi[N], pr[N][7];
int id[N]; bool vis[N];
vector <int> poly[N];
void prework () {
phi[1] = 1;
for (int i = 2; i < N; ++i) {
if (!pr[i][0])
for (int j = i; j < N; j += i)
pr[j][++pr[j][0]] = i;
phi[i] = i;
for (int j = 1; j <= pr[i][0]; ++j)
phi[i] -= phi[i] / pr[i][j];
}
}
bool cmp (int u, int v) {
if (phi[u] != phi[v]) return phi[u] < phi[v];
for (int i = phi[u]; ~i; --i) if (poly[u][i] != poly[v][i])
return poly[u][i] < poly[v][i];
return 0;
}
signed main () {
prework();
for (int _ = read(); _; --_) {
n = read(), m = 0;
for (int i = 1; i <= n; ++i) if (n % i == 0) {
id[++m] = i;
if (vis[i]) continue;
poly[i].resize(phi[i] + 1, 0);
poly[i][0] = i > 1 ? 1 : -1;
for (int j = 0; j < (1 << pr[i][0]); ++j) {
int d = i, s = 1;
for (int k = 0; k < pr[i][0]; ++k)
if (j >> k & 1) d /= pr[i][k + 1], s = -s;
if (s > 0)
for (int j = phi[i]; j >= d; --j)
poly[i][j] -= poly[i][j - d];
else
for (int j = d; j <= phi[i]; ++j)
poly[i][j] += poly[i][j - d];
}
vis[i] = 1;
}
sort(id + 1, id + 1 + m, cmp);
for (int i = 1, x; i <= m; ++i) {
x = id[i];
putchar('(');
for (int j = phi[x], f = 1; ~j; --j, f = 0) if (poly[x][j]) {
if (poly[x][j] < 0) putchar('-');
else if (!f) putchar('+');
if (!j || abs(poly[x][j]) != 1) printf("%d", abs(poly[x][j]));
if (j) printf("x");
if (j > 1) printf("^%d", j);
}
putchar(')');
}
putchar('\n');
}
return 0;
}
(输出复杂度可能是个瓶颈,本地测是输不出来的,但提交后跑得很快,AC)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· .NET Core GC压缩(compact_phase)底层原理浅谈
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp