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;
}
View Code

 

posted @ 2018-08-24 16:22  Jiaaaaaaaqi  阅读(112)  评论(0编辑  收藏  举报