zoukankan      html  css  js  c++  java
  • 【刷题记录】BZOJ2154 crash的数字表格 莫比乌斯反演

    治好了我多年的公式恐惧症

    https://www.luogu.org/problemnew/show/P1829

    (放洛谷题号的原因是BZOJ上很多内容是限制级的(雾))

    题目大意:已知M,N,求ans =sum_{i=1}^nsum_{j=1}^m{frac {ij} {(i,j)} }

    (我采用数论教材上的方法表示最大公因数,即(i,j)表示i,j的最大公约数)

    那么,我们开始吧。

    不妨设n<m

    d = (i,j),有ans = sum _{d=1}^{n} sum_{egin{matrix} (i,j)=d \ 1leqslant ileqslant n, \ 1leqslant j leqslant m, end{matrix}}frac {ij} d

    ans = sum _{d=1}^{n} dsum_{(i,j)=1}^{1leq ileq [frac nd],1leq jleq [frac md]}{ij}

    接下来是莫比乌斯函数的性质:sum _{x|d} mu (x) = 1当且仅当d = 1

    ans = sum _{d=1}^{n} dsum_{i=1}^{[frac nd]}sum_{j=1}^{[frac md]}sum_{x|(i,j)}mu (x){ij}

    转化为枚举x

    ans = sum_{d=1}^{ n}dsum_{x=1}^{[frac nd]}mu(x)x^2sum_{j=1}^{[frac n {dx}]}sum_{i=1}^{[frac m {dx}]}ij

    枚举t=dx

    ans = sum_{t=1}^{ n}tsum_{i=1}^{[frac nt]}sum_{j=1}^{[frac mt]}ijsum_{x|t}mu(x)x=sum_{t=1}^{ n}t(sum_{i=1}^{[frac nt]}i)(sum_{j=1}^{[frac mt]}j)sum_{x|t}mu(x)x

    中间两个和式为等差数列求和,可以O(1)得到结果

    经过完全归纳法证明,f(i)=sum_{x|i}mu(x)x为积性函数

    证明如下:

    当i为质数时,显然f(i)=1-i

    记p为任意质数

    (i,p)=1

    f(ip)=sum_{x|ip}xmu(x)=f(i)+sum _{xp|ip}(xp)mu(xp)=f(i)-pf(i)=f(p)*f(i)

    证完

    接下来考虑线性筛的实现

    考虑当(i,p)=p

    f(ip)=sum_{x|ip}xmu(x)=f(i)+sum _{xp|ip}(xp)mu(xp)=f(i)-0=f(i)

    所以线性筛完成

    依靠线性筛预处理后,可以O(n)时间预处理,再用O(n)时间得出结果

    然而此题还可以再次优化

    考虑到[frac nt][frac mt]可以数论分块

    时间复杂度可以优化至O(n+sqrt(n))

    这样可以解决多组数据的情况

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int n,m;
    #define ll long long
    #define mod 20101009
    #define inv2 10050505
    #define N 10000000
    int prime[N+9],mu[N+9];
    bool notprime[N+8];
    ll sum(int x)
    {
        return (((((ll)x*(x+1))%mod)*inv2)%mod);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        if(n>m)swap(n,m);
        notprime[1]=mu[1]=1;int tot = 0;
        for(int i = 2; i <= n; i ++)
        {
            if(!notprime[i])
            {
                prime[++tot]=i;
                mu[i]=(1-i+mod)%mod;
            }
            for(int j = 1; j <= tot &&prime[j]*i<=n; j ++)
            {
                notprime[prime[j]*i]=1;
                if(i%prime[j]==0)
                {
                    mu[i*prime[j]]=mu[i];
                    break;
                }
                else 
                {
                    mu[i*prime[j]]=(((ll)mu[i]*(1-prime[j])%mod)+mod)%mod;
                }
            }
            mu[i]=((((ll)i*mu[i])%mod+mu[i-1])%mod+mod)%mod;
        }
        int ans = 0;
        for(int i = 1,last; i <= n; i =last +1)
        {
            last = min(n/(n/i),m/(m/i));
            ans = (((((sum(n/i)*sum(m/i))%mod)*(mu[last]-mu[i-1]))%mod+mod)%mod+ans)%mod;
        }
        printf("%d",ans);
    }
  • 相关阅读:
    关于Ajax中this失效
    添加时间周期一年半年季度
    回车事件
    alt与title
    关于checked="checked"却不显示选中的“对勾”
    正则表达式的使用
    关于JQ 查找不到对象的clientHeight,
    Mysql笔记之 -- 开启Mysql慢查询
    Mysql笔记之 -- 小试MYSQL主从配置
    Linux系统学习笔记之 1 一个简单的shell程序
  • 原文地址:https://www.cnblogs.com/akonoh/p/10216755.html
Copyright © 2011-2022 走看看