题目传送门
分析:
开始玩一个小小的trick
我们发现(f(n)=sum_{d|n}mu(d)cdot d)是一个积性函数
所以:
(~~~~f(n)=prod f(p_i^{a_i}))
(~~~~f(gcd(x,y))cdot f(lcm(x,y))=prod f(p_i^{min(a_i,b_i)})cdot f(p_i^{max(a_i,b_i)}))
可以疯狂使用交换律然后。。。
(~~~~prod f(p_i^{min(a_i,b_i)})cdot f(p_i^{max(a_i,b_i)})=f(x)cdot f(y))
接下来就好办了,大力推:
(~~~~sum_{i=1}^{n}sum_{j=1}^{n}f(gcd(i,j))cdot f(lcm(i,j)))
(=sum_{i=1}^{n}sum_{j=1}^{n}f(i)cdot f(j))
(=(sum_{i=1}^{n}f(i))^2)
我们求里面的:
(~~~~sum_{i=1}^{n}sum_{d|i}mu(d)cdot d)
(=sum_{d=1}^{n}mu(d)cdot dcdot lfloorfrac{n}{d} floor)
分块处理(lfloorfrac{n}{d}
floor)
后面的老套路,卷一个(Id)
(~~~~sum_{i=1}^{n}sum_{d|i}mu(d)cdot dcdot frac{i}{d}=sum_{i=1}^{n}isum_{d|i}mu(d)=1)
(=sum_{d=1}^{n}dsum_{i=1}^{lfloorfrac{n}{d} floor}mu(i)cdot i)
把(d=1)提出来:
(~~~~sum_{i=1}^{n}mu(i)cdot i=1-sum_{d=2}^{n}dsum_{i=1}^{lfloorfrac{n}{d} floor}mu(i)cdot i)
(~~~~S(n)=1-sum_{d=2}^{n}dcdot S(lfloorfrac{n}{d} floor))
然后杜教筛就好了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<string>
#define maxn 100005
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define inv2 500000004
using namespace std;
inline long long getint()
{
long long num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
long long N;
long long pri[maxn],cnt,np[maxn],mu[maxn];
long long ans;
map<long long,long long>M;
inline void init()
{
mu[1]=1;
for(int i=2;i<maxn;i++)
{
if(!np[i])pri[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*pri[j]<maxn;j++)
{
np[i*pri[j]]=1;
if(i%pri[j]==0)break;
mu[i*pri[j]]=-mu[i];
}
}
for(int i=1;i<maxn;i++)(mu[i]*=i)%=MOD;
for(int i=1;i<maxn;i++)(mu[i]+=mu[i-1])%=MOD;
}
inline long long getans(long long x)
{
if(x<maxn)return mu[x];
if(M.count(x))return M[x];
long long num=1;
for(long long i=2,j;i<=x;i=j+1)
{
j=x/(x/i);
(num+=MOD-(i+j)*(j-i+1)%MOD*inv2%MOD*getans(x/i))%=MOD;
}
return M[x]=num;
}
int main()
{
N=getint();
init();
for(long long i=1,j;i<=N;i=j+1)
{
j=N/(N/i);
(ans+=(N/i)*(getans(j)-getans(i-1)))%=MOD;
}
printf("%lld
",(ans*ans%MOD+MOD)%MOD);
}