题目
题目:
经过重重笔试面试的考验,小明成功进入 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;
}