• [CSP-S模拟测试]:太阳神(莫比乌斯反演)


    题目描述

    太阳神拉很喜欢最小公倍数,有一天他想到了一个关于最小公倍数的题目。
    求满足如下条件的数对$(a,b)$对数:$a,b$均为正整数且$a,bleqslant n$而$lcm(a,b)>n$。其中的$lcm$当然表示最小公倍数。答案对$1,000,000,007$取模


    输入格式

    第一行一个正整数$n$。


    输出格式

    一行一个整数表示答案,对$1,000,000,007$取模。


    样例

    样例输入:

    3

    样例输出:

    2


    数据范围与提示

    对于$20\%$的数据$nleqslant 2,000$;
    对于$40\%$的数据$nleqslant 10,000,000$;
    对于$60\%$的数据$nleqslant 100,000,000$;
    对于$80\%$的数据$nleqslant 1,000,000,000$;
    对于$100\%$的数据$nleqslant 10,000,000,000$。


    题解

    一般遇到这种题,我们都是先将其化繁,再化简。

    就是我们现有一个简,但是时间复杂度高的算法;然后将其化为一个繁,时间复杂度依然高的算法;再将这个算法化成一个既简单时间复杂度又低的算法。

    那么我们先将其化繁,哦,不,先化简。

    发现直接求$lcm(a,b)>n$很不好求,不妨求其补集,也就是$lca(a,b)<=n$。

    开始化繁……

    我们知道,$lcm(a,b)=dfrac{a imes b}{gcd(a,b)}$,所以式子可以转化为:

    $sum limits_{i=1}^nsum limits_{j=1}^ndfrac{i imes j}{gcd(i,j)}leqslant n$

    将$gcd(i,j)$乘过去:

    $=sum limits_{i=1}^nsum limits_{j=1}^ni imes jleqslant gcd(i,j) imes n$

    发现,我们可以枚举$gcd$,也就是:

    $=sum limits_{g=1}^nsum limits_{i=1}^{left lfloor dfrac{n}{g} ight floor}sum limits_{j=1}^{left lfloor dfrac{n}{g} ight floor}i imes j imes g^2leqslant g imes n imes [gcd(i,j)==1]$

    约去一个$g$:

    $=sum limits_{g=1}^nsum limits_{i=1}^{left lfloor dfrac{n}{g} ight floor}sum limits_{j=1}^{left lfloor dfrac{n}{g} ight floor}i imes j imes gleqslant n imes [gcd(i,j)==1]$

    遇到长这样的$gcd$我们一般考虑莫比乌斯反演。

    那么我们又将其化成了:

    $sumlimits_{g=1}^nsumlimits_{d=1}^{leftlfloordfrac{n}{g} ight floor}mu (d)sumlimits_{i=1}^{leftlfloordfrac{n}{dg} ight floor}sumlimits_{j=1}^{leftlfloordfrac{n}{dg} ight floor}i imes j imes g imes d^2leqslant n$

    因为我们再枚举$leftlfloordfrac{n}{dg} ight floor$以上是没有用的,所以我们可以将其变成:

    $sum limits_{d=1}^{sqrt{n}}mu(d)sum limits_{g=1}^nsum limits_{i=1}^nsum limits_{j=1}^n i imes j imes gleqslant dfrac{n}{d^2}$

    那么,我们可以设$i<j<g$,但是需要注意得数需要乘$6$;再设$i,j,g$中有两个相等,那么得数要乘$3$就好啦。

    简略证明一下时间复杂度(不知道对不对):

    我们在调用函数的时候最外层循环是$i imes i imes ileqslant n$,内层循环是$i imes j imes jleqslant n$,在平面直角坐标系上积分可以得到函数的时间复杂度是$Theta({frac{n}{i^2}}^{frac{2}{3}})$,在考虑外面的$Theta(n^{frac{1}{2}})$即可得到总的时间复杂度是$Theta(n^{frac{2}{3}})$。

    时间复杂度:$Theta(n^{frac{2}{3}})$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1000000007;
    long long n;
    int pri[100001],mu[100001],cnt;
    bool v[100001];
    long long ans;
    void pre_work()
    {
        mu[1]=1;
        for(long long i=2;i<=100000;i++)
        {
            if(!v[i])mu[pri[++cnt]=i]=-1;
            for(int j=1;j<=cnt&&i*pri[j]<=100000;j++)
            {
                v[i*pri[j]]=1;
                if(i%pri[j])mu[i*pri[j]]=-mu[i];
                else{mu[i*pri[j]]=0;break;}
            }
        }
    }
    long long get(long long x)
    {
    	long long res=0;
    	for(long long i=1;i*i*i<=x;i++)
    	{
    		if(i*i*i<=x)res++;
    		for(long long j=i+1;i*j*j<x;j++)
    			res=(res+6*(x/i/j-j)%mod)%mod;
    	}
    	for(long long i=1;i*i<=x;i++)
    		res=(res+3*(x/i/i-(x/i/i>=i))%mod)%mod;
    	return res;
    }
    int main()
    {
    	pre_work();
    	scanf("%lld",&n);
    	for(long long i=1;i*i<=n;i++)
    		if(mu[i])ans=(ans+mu[i]*get(n/i/i)%mod)%mod;
    	n%=mod;
    	printf("%lld",(n*n-ans+mod)%mod);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    poj 2482 Stars in Your Window + 51Nod1208(扫描线+离散化+线段树)
    bzoj 1036: [ZJOI2008]树的统计Count (树链剖分+线段树 点权)
    树链剖分+线段树 单点修改 区间求和 模板
    bzoj 2124 等差子序列 (线段树维护hash)
    hdu 5638 Toposort (拓扑排序+线段树)
    hdu 5195 DZY Loves Topological Sorting (拓扑排序+线段树)
    Codeforces Round #250 (Div. 1) D. The Child and Sequence(线段树)
    hive 显示当前数据库名
    【Linux】ssh-keygen 的使用方法及配置 authorized_key s两台linux机器相互认证
    python email 模块
  • 原文地址:https://www.cnblogs.com/wzc521/p/11621299.html
Copyright © 2020-2023  润新知