【莫比乌斯】BZOJ 2818 Gcd
题意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对
思路:类似HDU 1695
代码:

#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; template <class T> inline bool rd(T &ret) { char c; int sgn; if(c = getchar() , c == EOF) return false; while(c != '-' && (c < '0' || c > '9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return true; } const int MAX_N = 10000007; bool vis[MAX_N]; int pcnt; int cnt[MAX_N], mu[MAX_N], prime[MAX_N]; void Mobius(int n) { pcnt = 0; vis[1] = mu[1] = 1; for(int i = 1;i <= n; i++) mu[i] = 1; for(int i = 2;i <= n; i++) { if(!vis[i]) { prime[pcnt++] = i; for(int j = i;j <= n;j += i) { vis[j] = 1; mu[j] *= -1; if((j/i) % i == 0) mu[j] = 0; int t = j; while(t % i == 0) t /= i, cnt[j]++; } } } } int n; int main() { rd(n); Mobius(n); ll ans = 0; for (int i = 0; i < pcnt && prime[i] <= n; ++i) { int m = n / prime[i]; for (int i = 1; i <= m; ++i) ans += (ll) mu[i] * (m / i) * (m / i); } printf("%lld\n", ans); return 0; }