乐趣区

莫比乌斯反演初步与实际应用

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

typedef long long LL ;
const int MAXN = 10000010 ;

long long T, N, M, V[MAXN], P[MAXN], Mu[MAXN], Tot ;
long long S[MAXN], Ans, G[MAXN] ;

inline long long Read() {
long long X = 0, F = 1 ; char ch = getchar() ;
while (ch > ‘9’ || ch < ‘0’) F = (ch == ‘-‘ ? – 1 : 1), ch = getchar() ;
while (ch >= ‘0’ && ch <= ‘9’) X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;
return X * F ;
}

inline void MU() {
memset(V, 0, sizeof(V)) ;
Mu[1] = 1 ; Tot = 0 ;
for (int i = 2 ; i < MAXN ; i ++) {
if (! V[i]) P[Tot ++] = i, Mu[i] = – 1, G[i] = 1 ;
for (int j = 0 ; j < Tot && i * P[j] < MAXN ; j ++) {
V[i * P[j]] = 1 ;
if (i % P[j]) Mu[i * P[j]] = – Mu[i],
G[i * P[j]] = Mu[i] – G[i] ; else {
Mu[i * P[j]] = 0 ; G[i * P[j]] = Mu[i] ;
break ;
}
}
}
for (int i = 1 ; i < MAXN ; i ++) S[i] = S[i – 1] + G[i] ;
}

int main() {
MU() ;
T = Read() ; while (T –) {
Ans = 0 ;
N = Read(), M = Read() ;
for (int i = 1, j ; i <= min(N, M) ; i = j + 1) {
j = min(N / (N / i), M / (M / i)) ;
Ans += (N / i) * (M / i) * (S[j] – S[i – 1]) ;
}
printf(“%lld\n”, Ans) ;
}
}

退出移动版