P8670 [蓝桥杯 2018 国 B] 矩阵求和 题解

题目传送门

前置知识

欧拉函数

解法

欧拉反演,简单地推下式子即可。

\(\begin{aligned}\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} \gcd(i,j)^{2} &=\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} \sum\limits_{d=1}^{n}d^{2} [\gcd(i,j)=d] \\ &=\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} \sum\limits_{d=1}^{n}d^{2} [\gcd(\dfrac{i}{d},\dfrac{j}{d})=1] \\ &=\sum\limits_{d=1}^{n}d^{2} \sum\limits_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor} \sum\limits_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor} [\gcd(i,j)=1] \\ &=\sum\limits_{d=1}^{n}d^{2} (-1+2 \sum\limits_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor} \varphi(i)) \end{aligned}\)

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
ll phi[10000001],prime[10000001],sum[10000001],len=0;
bool vis[10000001];
void euler(ll n)
{
	memset(vis,0,sizeof(vis));
	phi[1]=1;
	for(ll i=2;i<=n;i++)
	{
		if(vis[i]==false)
		{
			len++;
			prime[len]=i;
			phi[i]=i-1;
		}
		for(ll j=1;j<=len&&i*prime[j]<=n;j++)
		{
			vis[i*prime[j]]=true;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
			else
			{
				phi[i*prime[j]]=phi[i]*(prime[j]-1);
			}
		}
	}
}
int main()
{
	ll n,ans=0,i,p=1000000007;
	cin>>n;
	euler(n);
	for(i=1;i<=n;i++)
	{
		sum[i]=sum[i-1]+phi[i];
	}
	for(i=1;i<=n;i++)
	{
		ans=(ans+(i*i%p)*((2*sum[n/i]%p-1+p)%p)%p)%p;
	}
	cout<<ans<<endl;
	return 0;
}

后记

多倍经验:P2398

posted @ 2024-02-10 20:40  hzoi_Shadow  阅读(8)  评论(0编辑  收藏  举报
扩大
缩小