Loading

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);
}
posted @ 2020-08-31 15:54  MQFLLY  阅读(122)  评论(0编辑  收藏  举报