LOJ2185 约数个数和 数列

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 << '
';
	}
}
原文地址:https://www.cnblogs.com/hznumqf/p/14623335.html