Comet OJ 4266

题目描述

%   给定 n n n,求 ∑ i = 1 n ∑ j = 1 n d ( gcd ⁡ ( i , j ) ) \sum_{i=1}^n\sum_{j=1}^nd(\gcd(i,j)) i=1nj=1nd(gcd(i,j))

1 0 9 + 7 10^9+7 109+7 取模的结果,其中 d ( x ) d(x) d(x) 表示 x x x 的约数个数。
  数据范围 1 ⩽ n ⩽ 1 0 12 1\leqslant n\leqslant 10^{12} 1n1012

题目描述

%   先枚举 x = gcd ⁡ ( i , j ) x=\gcd(i,j) x=gcd(i,j),然后莫比乌斯反演常规套路。
∑ i = 1 n ∑ j = 1 n d ( ( i , j ) ) = ∑ x = 1 n ∑ i = 1 n ∑ j = 1 n d ( x ) [ ( i , j ) = x ] = ∑ x = 1 n ∑ i = 1 n x ∑ j = 1 n x d ( x ) ∑ d ∣ ( i , j ) μ ( d ) = ∑ x = 1 n d ( x ) ∑ i = 1 n x ∑ j = 1 n x ∑ d ∣ ( i , j ) μ ( d ) = ∑ x = 1 n d ( x ) ∑ d = 1 n μ ( d ) ⌊ n d x ⌋ 2 = ∑ i = 1 n ⌊ n i ⌋ 2 ∑ d ∣ i d ( i d ) μ ( d ) = ∑ i = 1 n ⌊ n i ⌋ 2 ( d ∗ μ ) ( i ) \begin{aligned}\sum_{i=1}^n\sum_{j=1}^nd((i,j)) &=\sum_{x=1}^n\sum_{i=1}^n\sum_{j=1}^nd(x)[(i,j)=x]\\ &=\sum_{x=1}^n\sum_{i=1}^{\frac nx}\sum_{j=1}^{\frac nx}d(x)\sum_{d|(i,j)}\mu(d)\\ &=\sum_{x=1}^nd(x)\sum_{i=1}^{\frac nx}\sum_{j=1}^{\frac nx}\sum_{d|(i,j)}\mu(d)\\ &=\sum_{x=1}^nd(x)\sum_{d=1}^n\mu(d)\left\lfloor\frac n{dx}\right\rfloor^2\\ &=\sum_{i=1}^n\left\lfloor\frac n{i}\right\rfloor^2\sum_{d|i} d(\frac id)\mu(d)\\ &=\sum_{i=1}^n\left\lfloor\frac n{i}\right\rfloor^2(d*\mu)(i)\\ \end{aligned} i=1nj=1nd((i,j))=x=1ni=1nj=1nd(x)[(i,j)=x]=x=1ni=1xnj=1xnd(x)d(i,j)μ(d)=x=1nd(x)i=1xnj=1xnd(i,j)μ(d)=x=1nd(x)d=1nμ(d)dxn2=i=1nin2did(di)μ(d)=i=1nin2(dμ)(i)

%   考虑到对于常函数 1 ( n ) = 1 1(n)=1 1(n)=1 和单位函数 ϵ ( n ) = [ n = 1 ] \epsilon(n)=[n=1] ϵ(n)=[n=1],有 1 ∗ μ = ϵ , 1 ∗ 1 = d 1*\mu=\epsilon,1*1=d 1μ=ϵ,11=d,因而
( d ∗ μ ) ( i ) = ( 1 ∗ 1 ∗ μ ) ( i ) = ( 1 ∗ ϵ ) ( i ) = 1 ( i ) = 1 (d*\mu)(i)=(1*1*\mu)(i)=(1*\epsilon)(i)=1(i)=1 (dμ)(i)=(11μ)(i)=(1ϵ)(i)=1(i)=1

%   因此有 ∑ i = 1 n ∑ j = 1 n d ( ( i , j ) ) = ∑ i = 1 n ⌊ n i ⌋ 2 \sum_{i=1}^n\sum_{j=1}^nd((i,j))=\sum_{i=1}^n\left\lfloor\frac n{i}\right\rfloor^2 i=1nj=1nd((i,j))=i=1nin2

%   直接除法分块即可。

代码

%   由于 n n n 的范围比较大,需要注意除法分块过程中不要忘记取模。

#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
#define int long long
signed main(){
	int n,T;
	scanf("%lld",&T);
	while(T--&&~scanf("%lld",&n)){
		int ans=0;
		for(int l=1,r;l<=n;l=r+1){
			r=n/(n/l);
			ans+=((n/l)%mod)*((n/l)%mod)%mod*((r-l+1+mod)%mod)%mod;
          ans%=mod;
		}
		printf("%lld\n",ans%mod);
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值