zoukankan      html  css  js  c++  java
  • 机房测试3:太阳神 ra (莫比乌斯反演)

    题目:

    分析:
    (终于在yyr大佬的援助下弄懂了这道题。。。)

    首先lcm>n的限制太少,不好直接处理,转换成求补集,也就是lcm<=n,最后用n^n-ans即可。

    考虑怎么求lcm<=n:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 100005
    #define ri register int
    const ll mod=1e9+7;
    int mu[N],lim,pri[N],su[N],cnt=0;
    void init()
    {
        mu[1]=1;
        for(ri i=2;i<=lim;++i){
            if(!pri[i]) mu[i]=-1,su[++cnt]=i;
            for(ri j=1;j<=cnt&&i*su[j]<=lim;++j){
                pri[i*su[j]]=1;
                if(i%su[j]==0) { mu[i*su[j]]=0; break; }
                else mu[i*su[j]]=-mu[i];
            }
        }
    }
    int main()
    {
        freopen("ra.in","r",stdin);
        freopen("ra.out","w",stdout);
        ll n;    
        scanf("%lld",&n);
        lim=(int)(sqrt(n)+0.5);
        init();
        ll anss=0;
        for(ri d=1;d<=lim;++d){
            ll tmp=n/d/d,ans=0;
            for(ll a=1;a*a*a<=tmp;++a)//在极小的范围里面枚举a和b 就可以得到c的范围 
             for(ll b=a;b*b<=tmp/a;++b){
                 ll c=tmp/a/b-b;//注意c是统计的范围 
                 if(a==b) ans=( ans + 1 + c*3 ) %mod;
                 else ans=( ans + 3 + c*6 ) %mod;
            }
            anss=( anss + mu[d]*ans )%mod;
        }
        n%=mod;
        printf("%lld
    ",(n*n%mod-anss+mod)%mod);
    }
    View Code

     最后得到一个三元组i,j,k,怎么统计答案呢

    首先三者的大小关系是:i<=j<=k

    1.i==j :即 有两个是相同的排列: i i j  , i j i,j i i,所以要*3,还要+1。(i==j==k)

    2.i !=j  : 一种是三个不同的全排列*6,另一种是j==k情况下还要+3种(注意此时i不能=k,因为有范围限制)

     

     

     

  • 相关阅读:
    summernote 上传图片到图片服务器的解决方案(springboot 成功)
    rabbitmq 命令行与控制台
    redis 集群
    rabbitmq快速安装(实测有效)(新版)
    设计模式-5适配器模式
    Nginx做缓存
    Redis的高可用
    正则表达式
    常用的实例场景(.net js jq)
    sentry的安装
  • 原文地址:https://www.cnblogs.com/mowanying/p/11623314.html
Copyright © 2011-2022 走看看