题目:
分析:
(终于在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); }
最后得到一个三元组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,因为有范围限制)。