题目

题目:

经过重重笔试面试的考验,小明成功进入 Macrohard 公司工作。
今天小明的任务是填满这么一张表:
表有 n 行 n 列,行和列的编号都从1算起。
其中第 i 行第 j 个元素的值是 gcd(i, j)的平方,
gcd 表示最大公约数,以下是这个表的前四行的前四列:
1 1 1 1
1 4 1 4
1 1 9 1
1 4 1 16

小明突然冒出一个奇怪的想法,他想知道这张表中所有元素的和。
由于表过于庞大,他希望借助计算机的力量。

题解:

已知可以用欧拉函数和莫比乌斯反演来做
题目其实就是问

欧拉函数:


莫比乌斯反演:

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+9;
typedef long long ll;
bool vis[maxn];
ll prime[maxn];
ll phi[maxn];
ll s[maxn];

const int mod=1e9+7;
void Euler(int n)
{
   
	phi[1]=1;
	int cnt=0;
	for(int i=2;i<=n;i++)
	{
   
		if(!vis[i])
		{
   
			prime[cnt++]=i;
			phi[i]=i-1;
		}
		for(int j=0;j<cnt&&i*prime[j]<=n;j++)
		{
   
			vis[prime[j]*i]=1;
			if(i%prime[j])
			{
   
				phi[i*prime[j]]=phi[i]*(prime[j]-1);
			}
			else 
			{
   
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
		 } 
	}
	s[1]=phi[1];
	for(int i=2;i<n;i++)
	{
   
		s[i]=s[i-1]+2*phi[i];
	}
}
int main()
{
   
	int n;
	Euler(maxn);
	ll sum=0;
	while(cin>>n)
	{
   
		sum=0;
		for(ll i=1;i<=n;i++)
		sum=(sum+s[n/i]%mod*i%mod*i%mod)%mod;
		cout<<sum<<endl;
	}
}
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int mod=1e9+7;
const int maxn = 10000000 + 10;
ll mu[maxn], vis[maxn], prim[maxn];
ll cnt = 0;		//素数的个数
ll d[maxn];
ll sum(int n)
{
   
	ll ans=0;
	for(int l=1,r;l<=n;l=r+1)		//整除分块 
	{
   
		r=n/(n/l);
		ans=(ans+(mu[r]-mu[l-1]+mod)%mod*((ll)n/l)%mod*((ll)n/l)%mod)%mod;
	}
	return ans;
}
void get_mu(int n)
{
   
	mu[1] = 1;
	for (int i = 2; i <= n; i++)
	{
   
		if (!vis[i]) {
    prim[++cnt] = i; mu[i] = -1; }
		for (int j = 1; j <= cnt && prim[j] * i <= n; j++)
		{
   
			vis[prim[j] * i] = 1;
			if (i%prim[j] == 0)break;
			else mu[i*prim[j]] = -mu[i];
		}
	}
	for(int i=1;i<=n;i++)
	{
   
		d[i]=((ll)i*i)%mod;
	}
	for(int i=2;i<=n;i++)
	{
   
		d[i]=(d[i-1]+d[i])%mod;			//d的前缀和 
		mu[i]=(mu[i-1]+mu[i]+mod)%mod;	//mu的前缀和 
	}
	ll ans=0;
	for(int l=1,r;l<=n;l=r+1)			//整除分块 
	{
   
		r=n/(n/l);
		ans=(ans+(ll)(d[r]-d[l-1]+mod)%mod*(ll)sum(n/l)%mod)%mod;
	}
	cout<<ans<<endl;
}
int main()
{
   
	int n;
	cin>>n;
	get_mu(n);
	return 0;
}