HNOI 2002 跳蚤 容斥,莫比乌斯反演
HNOI 2002 跳蚤 容斥,莫比乌斯反演
题意
一只跳蚤目前站在无限长的绳索中央,给出一张卡牌,上面有\(n+1\) 个自然数,其中最后一个数字为\(m\) 。
跳蚤可以选择卡牌给的数字跳任意次,只要最终能够到达左边\(1\) 单位即可。
现在给定\(n,m\) ,问有多少张卡牌可以满足要求
\[n,m\leq 10^8,m^n\leq 10^{16}
\]
分析
一张牌能够跳到最左端,需要满足
\[\sum a_ix_i = 1
\]
根据裴蜀定理,该方程要有解等价于
\[(a_1,a_2...a_n,a_{n+1})=1
\]
那么答案就可以写成
\[\sum _{a_1=1}^m\sum _{a_2=1}^m...\sum _{a_n=1}^m[gcd(a_1,a_2...a_n,m) = 1]
\\
=\sum _{a_1=1}^m\sum _{a_2=1}^m...\sum _{a_n=1}^m \epsilon(gcd(a_1,a_2...a_n,m))
\\
=\sum _{a_1=1}^m\sum _{a_2=1}^m...\sum _{a_n=1}^m \sum _{d|a_i,d|m} \mu(d)
\\
=\sum _{d|m} \mu(d)\cdot (\frac{m}{d})^n
\]
复杂度\(O(\sqrt{m}logn)\)
注意这里实现,如果暴力求出莫比乌斯函数,再枚举\(m\) 的因子复杂度会达到\(O(m)\)
所以求这个表达式的时候考虑莫比乌斯函数的性质,只需要考虑其中的质因子,然后\(dfs\) 一下质因子的贡献,复杂度就降到了\(O(2^{f(m)})\) ,其中\(f\) 表示质因子的个数
代码
int cnt;
ll res;
int n, m;
int pri[20];
void dfs(int cur, int p, int mu) {
if (cur == cnt) {
res += mu * ksm(m / p, n);
return;
}
dfs(cur + 1, p, mu);
dfs(cur + 1, p * pri[cur], -mu);
}
int main() {
n = readint();
m = readint();
int k = m;
for (int i = 2; i * i <= m; i++) {
if (k % i == 0) {
pri[cnt++] = i;
while (k % i == 0) k /= i;
}
}
if (k != 1) pri[cnt++] = k;
dfs(0, 1, 1);
Put(res);
}