题目:
分析:
(终于在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); }
原文地址:https://www.cnblogs.com/mowanying/p/11623314.html
时间: 2024-09-29 18:48:39