题目:

 

 

分析:
(终于在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*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,因为有范围限制)

 

 

 

 

 

 

 

 

 

 

posted on 2019-10-04 21:10  rua-rua-rua  阅读(286)  评论(0编辑  收藏  举报