P3327 [SDOI2015] 约数个数和 题解

P3327 [SDOI2015] 约数个数和

题意:

设 \(d(x)\) 为 \(x\) 的约数个数,给定 \(n,m\),求

\[\sum_{i=1}^n\sum_{j=1}^md(ij) \]

思路:

\(\displaystyle \sum_{i=1}^n\sum_{j=1}^md(ij)=\sum_{i=1}^n\sum_{j=1}^m \sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]\)
\(\displaystyle =\sum_{x=1}^n\sum_{y=1}^m \lfloor\frac{n}{x} \rfloor\lfloor\frac{m}{y} \rfloor[\gcd(x,y)=1]\)
\(\displaystyle =\sum_{x=1}^n\sum_{y=1}^m \lfloor\frac{n}{x} \rfloor\lfloor\frac{m}{y} \rfloor\sum_{d|\gcd(x,y)}\mu(d)\)
\(\displaystyle =\sum_{x=1}^n\sum_{y=1}^m \lfloor\frac{n}{x} \rfloor\lfloor\frac{m}{y} \rfloor\sum_{d=1}^{n}[d|x][d|y]\mu(d)\)
\(\displaystyle =\sum_{d=1}^{n}\mu(d)(\sum_{x=1}^n\lfloor\frac{n}{x} \rfloor[d|x])(\sum_{y=1}^m \lfloor\frac{m}{y} \rfloor[d|y])\)
\(\displaystyle =\sum_{d=1}^{n}\mu(d)(\sum_{x=1}^{\lfloor\frac{n}{d} \rfloor}\lfloor\frac{\lfloor\frac{n}{d} \rfloor}{x} \rfloor)(\sum_{y=1}^{\lfloor\frac{m}{d} \rfloor}\lfloor\frac{\lfloor\frac{m}{d} \rfloor}{y} \rfloor)\)
然后直接计算即可。

代码

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define double long double
#define PII pair<int,int>
using namespace std;
mt19937_64 rng(time(0));

const int N = 1e6 + 10, M = 1e3, mod = 19940417;
const double EPS = 1e-8;


int qpow(int x, int n) {
	int ans = 1;
	while (n) {
		if (n & 1) {
			ans *= x;
			ans %= mod;
		}
		x *= x;
		x %= mod;
		n >>= 1;
	}
	return ans;
}
//int fac[N];
//int inv[N];
//void init(){
//	fac[0]=inv[0]=1;
//	for(int i=1;i<N;i++){
//		fac[i]=fac[i-1]*i%mod;
//	}
//	inv[N-1]=qpow(fac[N-1],mod-2);
//	for(int i=N-2;i>=0;i--){
//		inv[i]=inv[i+1]*(i+1)%mod;
//	}
//}
//
//
//int C(int n,int m){
//	return fac[n]*inv[m]%mod*inv[n-m]%mod;
//}
int mu[N], p[N],smu[N];
bool flg[N];
int tot = 0;
void getMu(int n) {
	mu[1] = 1;
	for (int i = 2; i <= n; ++i) {
		if (!flg[i]) p[++tot] = i, mu[i] = -1;
		for (int j = 1; j <= tot && i * p[j] <= n; ++j) {
			flg[i * p[j]] = 1;
			if (i % p[j] == 0) {
				mu[i * p[j]] = 0;
				break;
			}
			mu[i * p[j]] = -mu[i];
		}
	}
	for(int i=2;i<=n;i++){
		mu[i]+=mu[i-1];
	}
}


ll H(int n){
	ll res=0;
	int l=1,r;
	while(l<=n){
		r=n/(n/l);
		res+=(ll)(r-l+1)*(n/l);
		l=r+1;
	}
	return res;
}

ll h[N];
ll H1(int n,int m){
	ll res=0;
	int l=1,r;
	while(l<=n&&l<=m){
		r=min(n/(n/l),m/(m/l));
		res+=(mu[r]-mu[l-1])*h[n/l]*h[m/l];
		l=r+1;
	}
	return res;
}
void solve() {
	int n,m;
	cin>>n>>m;
	ll ans=H1(n,m);
	cout<<ans<<endl;

}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t = 1;
	cin >> t;
//	init();
	getMu(5e4);
	for(int i=1;i<=5e4;i++){
		h[i]=H(i);
	}
	while (t--) {
		solve();
	}

	return 0;
}
posted @ 2026-09-24 14:11  ptlks  阅读(10)  评论(0)    收藏  举报