思路
题意是求
莫比乌斯反演最重要的当然就是推柿子.假设,不满足的话swap一下就OK了
这就是一个用数论分块可以解决的东西.只要预处理一下前缀和就OK了.
数论分块一次的复杂度为,因此总复杂度为
.
因为不是很卡常数所以没有优化除法....
至于如何优化除法 可以参考https://www.luogu.org/problemnew/solution/SP26045
代码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 50000
int T;
int mu[MAXN + 5], p[MAXN + 5], tot;
bool v[MAXN + 5];
int Work( int N, int M ){ int ans(0); if ( N > M ) swap( N, M );
for ( int i = 1, j; i <= N; i = j + 1 ){
j = min( N / ( N / i ), M / ( M / i ) );
ans += ( N / i ) * ( M / i ) * ( mu[j] - mu[i - 1] );
} return ans;
}
int main(){
scanf( "%d", &T ); mu[1] = 1;
for ( int i = 2; i <= MAXN; ++i ){
if ( !v[i] ) p[++tot] = i, mu[i] = -1;
for ( int j = 1; j <= tot && i * p[j] <= MAXN; ++j ){
v[i * p[j]] = 1; mu[i * p[j]] = i % p[j] ? -mu[i] : 0;
if ( i % p[j] == 0 ) break;
}
}
for ( int i = 1; i <= MAXN; ++i ) mu[i] += mu[i - 1];
while( T-- ){
int a, b, d;
scanf( "%d%d%d", &a, &b, &d ); a /= d; b /= d;
printf( "%d\n", Work( a, b ) );
}
return 0;
} 
京公网安备 11010502036488号