• [51nod1244]莫比乌斯函数之和


    题意:求区间[a,b]的莫比乌斯函数µ之和。  a,b<=$10^{11}$

    题解:很容易把区间求和改为求前缀和并求差,即要求$M(x)=sum_{1}^{n}mu(x)$考虑化简

    莫比乌斯函数存在一个性质,也就是$sum_{d|n}^{ } mu(d)= [n=1]$,那么$sum_{i=1}^{n}sum_{d|i}^{ } mu(d)= 1$ 

    这个式子比较复杂,我们转而考虑对于每一个d,它被计算了多少次,也就是$sum_{i=1}^{n}sum_{d=1}^{lfloor n/i floor} mu(d)$ ,这个式子=$sum_{i=1}^{n}M(lfloor n/i floor)$=1  所以说,$M(n)=1-sum_{i=2}^{n}M(lfloor n/i floor)$

    $lfloor n/i floor$/i只有$sqrt(n)$种,复杂度在预处理出前$k=n^{frac{2}{3}}$的M值时最小,然后记忆化搜索可以在$O(n^{frac{2}{3}})$内解决。

    我们发现在计算中$lfloor n/i floor$有很多会被重复计算,所以可以手写一个map来极大地提升效率。

    第一次用latex写公式,还好有个很牛逼的网站

    估计是模数选的好,随便写写RANK1啦。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define MAXN 5000000
    #define mod 2333333
    #define ll long long
    using namespace std;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    struct my_map{
        ll x;int ans,next;
    }e[MAXN+5];
    int f[MAXN+5],ans=0,num=0,s[MAXN],head[mod+5];
    bool b[MAXN+5];
    
    void ins(ll x,int sum)
    {
        int j=x%mod;
        e[++num]=(my_map){x,sum,head[j]};
        head[j]=num;
    }
    
    int calc(ll n)
    {
        if(n<=MAXN) return f[n];
        for(int i=head[n%mod];i;i=e[i].next)
            if(e[i].x==n)return e[i].ans;
        int sum=1,q=sqrt(n);
        for(int i=2;i<=q;i++)
            sum-=calc(n/i);
        q=n/(q+1);
        for(int i=1;i<=q;i++)
            sum-=(n/i-(n/(i+1)))*calc(i);
        ins(n,sum);
        return sum;
    }
    
    int main()
    {
        f[1]=1;b[1]=1;
        for(int i=2;i<=MAXN;i++)
        {
            if(!b[i]) s[++num]=i,f[i]=-1;
            for(int j=1;j<=num&&s[j]*i<=MAXN;j++)
            {
                int t=s[j]*i; b[t]=1;
                if(i%s[j]==0){f[t]=0;break;}
                f[t]=-f[i];
            }
        }
        for(int i=2;i<=MAXN;i++)
            f[i]+=f[i-1];
        num=0;
        ll x=read();ans-=calc(x-1);
        x=read();ans+=calc(x);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    WPF控件操作之改变父控件之TabControl示例
    WPF里面的DockPanel的Fill去哪了,如何填满整个空间
    [原创]winform自定义控件之类属性-多重属性-可折叠属性
    WinForm之DataBinding
    WinForm自定义控件之DefaultValue的误解
    code snippet:依赖属性propa的小技巧
    【原创】WinForm中实现单独Time控件的方式
    node.js安装本地模块遇到的目录锁定问题【新手问题】
    《程序员思维修炼》之德雷福斯模型
    IOptions、IOptionsMonitor以及IOptionsSnapshot
  • 原文地址:https://www.cnblogs.com/FallDream/p/51nod1244.html
Copyright © 2020-2023  润新知