bzoj 1101 莫比乌斯反演
最裸的莫比乌斯
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 1e5 + 7; const int M = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int p[N], is[N], mbs[N], sum[N], n, m, d, ans, tot; void init(){ memset(is, 1 ,sizeof(is)); mbs[1]=1; for(int i = 2; i < N; i++) { if(is[i]){ p[++tot] = i; mbs[i] = -1; } for(int j = 1; j <= tot && p[j] * i < N; j++){ is[i * p[j]] = 0; if(i % p[j] == 0){ mbs[i * p[j]] = 0; break; } else { mbs[i * p[j]] = -mbs[i]; } } } for(int i = 1; i < N; i++) { sum[i] = mbs[i] + sum[i - 1]; //维护前缀和 } } int cal(int n, int m){ //求[1,n][1,m]区间内互质的(x, y)的对数 int ans=0; if(n > m) swap(n, m); for(int L = 1, R=0; L <= n; L = R + 1) { R = min(n / (n / L), m /(m / L)); // 分段加速 ans += (sum[R] - sum[L - 1]) * (n / L) * (m / L); } return ans; } int main(){ init(); int T; scanf("%d", &T); while(T--) { scanf("%d%d%d",&n,&m,&d); ans = cal(n / d, m / d); printf("%d\n", ans); } return 0; } /* */