A40809. 矩阵求和
填空题
困难
知识点
题目描述
矩阵求和
题目描述
经过重重笔试面试的考验,小明成功进入 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 意义见题。
对于 30% 的数据,n <= 1000
存在 10% 的数据,n = 10^5
对于 60% 的数据,n <= 10^6
对于 100% 的数据,n <= 10^7
输出格式
一行一个数,表示所有元素的和。由于答案比较大,请输出模 (10^9 + 7)(即:十亿零七) 后的结果。
样例输入
4
样例输出
48
参考答案
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e7+10;
ll mu[N];
int pri[N],num;
bool st[N];
void init_pri(ll n){
mu[1]=1;
st[1]=true;
for(int i=2;i<=n;++i){
if(!st[i]){
pri[++num]=i;
mu[i]=((1ll*i*i-1)%mod+mod)%mod;
}
for(int j=1;i*pri[j]<=n;++j){
st[i*pri[j]]=true;
if(i%pri[j]==0){
mu[i*pri[j]]=1ll*mu[i]*pri[j]%mod*pri[j]%mod;
break;
}
mu[i*pri[j]]=((1ll*mu[i]*mu[pri[j]])%mod+mod)%mod;
}
}
for(int i=1;i<=n;++i){
mu[i]=((mu[i]+mu[i-1])%mod+mod)%mod;
}
}
ll calc(ll n){
ll l=1,r;
ll ans=0;
for(;l<=n;l=r+1){
r=n/(n/l);
ans=(ans+1ll*(mu[r]-mu[l-1])%mod*(n/l)%mod*(n/l)%mod)%mod;
if(ans<0)ans+=mod;
}
return ans;
}
int main()
{
ll n;
cin>>n;
init_pri(n);
cout<<calc(n)<<endl;
}
上一题
下一题