题意
已知
f(x)=∑d|xμ(d)∗d
现在请求出下面式子的值
∑i=1n∑j=1nf(gcd(i,j))∗f(lcm(i,j))
答案模1e9+7。
n<=109
分析
设
x=pa11∗...∗pakk
,那么有
f(x)=∏i=1k(1−pi)
。这步十分的关键。
然后就可以得到
f(i)∗f(j)=f(i∗j)∗f(gcd(i,j))
f(lcm(i,j))=f(i∗j)
所以
f(gcd(i,j))∗f(lcm(i,j))=f(gcd(i,j))∗f(i∗j)=f(i)∗f(j)
所以说答案就是
(∑i=1nf(i))2
。
然后就可以爱怎么搞怎么搞了。
要求
∑i=1nμ(i)∗i
这个东西显然是个积性函数,考虑用杜教筛来做。将 f(x) 卷上 g(x)=x 那么有
∑i=1n∑d|iμ(d)∗d∗id=∑i=1n∑d|imu(id)∗id∗d
其中左边的部分就等于1,右边的部分有
∑i=1n∑d|imu(id)∗id∗d
=∑i=1ni∗∑d|iμ(id)
=∑d=1nd∗∑i=1⌊nd⌋μ(i)∗i
这就可以用杜教筛来搞了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
const int N=10000005;
const int MOD=1000000007;
int n,s[N],tot,prime[N];
bool not_prime[N];
map<int,int> w;
void get_prime(int n)
{
s[1]=1;
for (int i=2;i<=n;i++)
{
if (!not_prime[i]) prime[++tot]=i,s[i]=-1;
for (int j=1;j<=tot&&i*prime[j]<=n;j++)
{
not_prime[i*prime[j]]=1;
if (i%prime[j]==0) break;
s[i*prime[j]]=-s[i];
}
}
for (int i=1;i<=n;i++) s[i]=(s[i-1]+s[i]*i)%MOD;
}
int get_sum(int l,int r)
{
return ((LL)r*(r+1)/2-(LL)l*(l-1)/2)%MOD;
}
int get_s(int n)
{
if (n<=10000000) return s[n];
if (w[n]) return w[n];
int ans=1;
for (int i=2,last;i<=n;i=last+1)
{
last=n/(n/i);
(ans-=(LL)get_sum(i,last)*get_s(n/i)%MOD)%=MOD;;
}
return w[n]=ans;
}
int main()
{
scanf("%d",&n);
get_prime(10000000);
int ans=0;
for (int i=1,last;i<=n;i=last+1)
{
last=n/(n/i);
(ans+=(LL)(n/i)*(get_s(last)-get_s(i-1))%MOD)%=MOD;
}
ans+=ans<0?MOD:0;
printf("%d",(LL)ans*ans%MOD);
return 0;
}