Visible Trees HDU - 2841(容斥)
对于已经满足条件的(x1,y1),不满足条件的点就是(n*x1,n*y1),所以要求的就是满足点(x,y)的x,y互质,也就是gcd(x,y) == 1,然后就可以用之前多校的方法来做了
另f[i] 表示gcd为 i 的倍数的对数
g[i] 表示gcd == i 的对数
f[i] = (n/i) * (m/i)
g[i] = f[i] - g[x*i] (x>=2)
然后容斥出来的g[1]就是对数
#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define lowbit(x) (x & (-x)) #define INOPEM freopen("in.txt", "r", stdin) #define OUTOPEN freopen("out.txt", "w", stdout) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 100005; const int maxm = 1005000; const int mod = 1e9+7; using namespace std; int n, m; int T, tol; ll f[maxn]; ll g[maxn]; void init() { memset(f, 0, sizeof f); memset(g, 0, sizeof g); } int main() { scanf("%d", &T); while(T--) { init(); scanf("%d%d", &n, &m); if(n > m) swap(n, m); for(int i=1; i<=n; i++) f[i] = 1ll * (n/i) * (m/i); for(int i=n; i>=1; i--) { g[i] = f[i]; for(int j=2; i*j<=n; j++) { g[i] -= g[i*j]; } } printf("%lld\n", g[1]); } return 0; }