LOJ2185 约数个数和 数列
题意
求
[sum_{i=1}^nsum_{j=1}^m d(ij) ,d(x)表示x的约数个数\
n,m leq 5e4
]
分析
[d(ij) = sum_{x|i}sum_{y|j} [(x,y) = 1]
]
[ans = sumsum d(ij)\
=sum sum sum_{x|i} sum_{y|j} [(x,y) = 1]\
=sum_{x=1}^n sum_{y=1}^m lfloor frac{n}{x}
floor lfloor frac{m}{y}
floor sum_{d|x,d|y} mu(d)\
= sum_{d = 1}^{min(n,m)} mu(d) sum_{i=1}^{lfloor frac{n}{d}
floor} sum_{j=1}^{lfloorfrac{m}{d}
floor} lfloor frac{n}{id}
floor lfloor frac{m}{id}
floor\
= sum_{d=1}^{min(n,m)} mu(d) sum_{i=1}^{lfloor frac{n}{d}
floor} lfloor frac{n}{id}
floor sum_{j=1}^{lfloor frac{m}{d}
floor} lfloor frac{m}{id}
floor \
= sum_{d=1}^{min(n,m)} mu(d) t(lfloor frac{n}{d}
floor)t(lfloor frac{m}{d}
floor)
]
预处理出(t),对原式整除分块即可
复杂度(O(Tsqrt{n} + nsqrt{n}))
代码
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define re register
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1e9 + 7;
const int maxn = 5e4 + 5;
ll rd(){
ll x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
ll t[maxn];
int prime[maxn], prime_tot;
int is_prime[maxn];
int mu[maxn];
void pre_calc(int lim) {
mu[1] = 1;
for (int i = 2; i <= lim; i++) {
if (!is_prime[i]) {
prime[++prime_tot] = i;
mu[i] = -1;
}
for (int j = 1; j <= prime_tot; j++) {
if (i * prime[j] > lim) break;
is_prime[i * prime[j]] = 1;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
}
else mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i <= lim;i++)
mu[i] += mu[i - 1];
}
int main(){
pre_calc(maxn - 3);
for(int i = 1;i <= maxn - 5;i++){
for(int j = 1,k;j <= i;j = k + 1) {
k = i / (i / j);
t[i] += (ll)(i / j) * (k - j + 1);
}
}
int T = rd();
while(T--){
int n = rd();
int m = rd();
int nn = min(n,m);
ll ans = 0;
for(int i = 1,j;i <= nn;i = j + 1) {
j = min(n / (n / i),m / (m / i));
ans += (ll)t[n / i] * t[m / i] * (mu[j] - mu[i - 1]);
}
cout << ans << '
';
}
}