版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/89607310
第六题
标题:矩阵求和
经过重重笔试面试的考验,小明成功进入 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
小明突然冒出一个奇怪的想法,他想知道这张表中所有元素的和。 由于表过于庞大,他希望借助计算机的力量。
「输入格式」 一行一个正整数 n 意义见题。
「输出格式」 一行一个数,表示所有元素的和。由于答案比较大,请输出模 (10^9 + 7)(即:十亿零七) 后的结果。
「样例输入」 4
「样例输出」 48
「数据范围」 对于 30% 的数据,n <= 1000 存在 10% 的数据,n = 10^5 对于 60% 的数据,n <= 10^6 对于 100% 的数据,n <= 10^7
分析:欧拉函数+莫比乌斯反演
莫比乌斯反演:https://blog.csdn.net/ACdreamers/article/details/8542292
#include <iostream>
using namespace std;
const int N = 1e7+5, MOD = 1e9+7;
long long phi[N], sum[N];
// 欧拉线性筛+求欧拉函数模板
void euler_table(int n){
phi[1] = 1;
for(long long i = 2; i <= n; i++){
if(!phi[i]){
for(long long j = i; j <= n; j += i){
if(!phi[j]) phi[j] = j;
phi[j] = phi[j]/i*(i-1);
}
}
}
sum[1] = 1; //sum表示n阶矩阵中i和j互质的个数。
for(int i = 2; i <= n; i++)
sum[i] = sum[i-1] + phi[i]*2;
}
int main(int argc, char** argv) {
int n;
cin>> n;
euler_table(n);
long long ans = 0;
for(int i = 1; i <= n; i++)
ans = (ans + sum[n/i]* i%MOD* i%MOD)%MOD;
cout<< ans << "\n";
return 0;
}