P1829 [国家集训队]Crash的数字表格 / JZPTAB

莫比乌斯反演

f(n)=d|ng(d)g(n)=d|nμ(d)f(nd)

f(n),g(n) 均为积性函数。

f(n) 称为 g(n) 的莫比乌斯变换。

g(n) 称为 f(n) 的莫比乌斯逆变换。

这里需要复习一下狄利克雷卷积和常用卷积关系: (fg)(n)=d|nf(d)g(nd)=d|nf(nd)g(d)

于是推证莫比乌斯反演:

f=g1,则 μf=μg1=gμ1=gε=g

g=μf,则 g1=μf1=fμ1=fε=f

此处有一个nb的证明方法,我并没有太懂

例题

P1829 [国家集训队]Crash的数字表格 / JZPTAB

给出 n,m,求 i=1nj=1mlcm(i,j)(mod20101009),数据规模 n,m107

分析:

[gcd(i,j)=1]=d|gcd(i,j)μ(d)


代码实现:calc函数 O(NN)=O(N),init函数 O(N)

#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 10000010;
const int P = 20101009;
int vis[N], p[N], mu[N], S[N], cnt;

void init()
{
    mu[1] = 1;
    for (int i = 2; i < N; ++i)
    {
        if (!vis[i])
            p[++cnt] = i, mu[i] = -1;
        for (int j = 1; i * p[j] < N; ++j)
        {
            vis[i * p[j]] = 1;
            if (i % p[j] == 0)
                break;
            mu[i * p[j]] = -mu[i];
        }
    }
    for (int i = 1; i < N; ++i)
        S[i] = (S[i - 1] + 1LL * mu[i] * i * i % P + P) % P;
}
int G(int n, int m)
{
    return (1LL * n * (n + 1) / 2 % P) * (1LL * m * (m + 1) / 2 % P) % P;
}
int F(int n, int m)
{
    int res = 0;
    for (int l = 1, r; l <= n; l = r + 1)
    {
        r = min(n / (n / l), m / (m / l)); // 分块的灵活运用
        res = (res + 1LL * (S[r] - S[l - 1]) * G(n / l, m / l) % P + P) % P;
    }
    return res;
}
int calc(int n, int m)
{
    if (n > m)
        swap(n, m);
    int res = 0;
    for (int l = 1, r; l <= n; l = r + 1)
    {
        r = min(n / (n / l), m / (m / l));
        res = (res + 1LL * (r - l + 1) * (l + r) / 2 % P * F(n / l, m / l) % P) % P;
    }
    return res;
}
int main()
{
    init();
    int n, m;
    scanf("%d%d", &n, &m);
    printf("%d\n", calc(n, m));
}
posted @   Vegdie  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示