太阳神 [莫比乌斯反演]

比较容易想到,先将 > n 转换成 <= n

ans=n^2 -\sum_{i=1}^n\sum_{j=1}^n [\frac{ij}{(i,j)}<=n]=n^2 - \sum_{d=1}^n \sum_{i=1}^{n/d}\sum_{j=1}^{n/d}[ijd<=n][(i,j)=1]=n^2 - \sum_{l=1}^{\sqrt{n}}\mu(l)\sum_d \sum_i\sum_j [ijd<=n/l^2]

然后就可以直接暴力枚举 l,然后快速计算 (d, i, j) 的对数

不妨设 d <= i <= j,然后 d 只需要枚举到 N^{ \frac{ 1 }{ 3} }, (N=n/l^2), i 从 d 开始枚举到 \sqrt{\frac{N}{d}}, 就可以暴力怼过


#include<bits/stdc++.h>
#define N 100050
using namespace std;
typedef long long ll;
const int Mod = 1000000007;
ll n;
int prim[N], isp[N], mu[N], tot;
void prework(){
	mu[1] = 1;
	for(int i = 2; i <= N-50; i++){
		if(!isp[i]) prim[++tot] = i, mu[i] = -1;
		for(int j = 1; j <= tot; j++){
			if(i * prim[j] > N-50) break;
			isp[i * prim[j]] = 1;
			if(i % prim[j] == 0){ mu[i * prim[j]] = 0; break;}
			mu[i * prim[j]] = mu[i] * mu[prim[j]];
		}
	}
}
int main(){
	scanf("%lld", &n); prework();
	ll x = n % Mod, ans = (x * x) % Mod;
	for(ll i = 1; i * i <= n; i++){
		if(!mu[i]) continue;
		ll m = n / i / i, sum = 0;
		for(ll a = 1; a * a * a <= m; a++){
			for(ll b = a; a * b * b <= m; b++){
				ll c = m / a / b - b + 1;
				if(a == b) sum = (sum + 1 + (c - 1) * 3) % Mod;
				else sum = (sum + 3 + (c - 1) * 6) % Mod;
			}
		} ans = (ans - mu[i] * sum) % Mod;
	} cout << (ans % Mod + Mod) % Mod;
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值