zoukankan      html  css  js  c++  java
  • HDU 2841 Visible Trees(容斥)题解

    题意:有一块(1,1)到(m,n)的地,从(0,0)看能看到几块(如果两块地到看的地方三点一线,后面的地都看不到)。

    思路:一开始是想不到容斥...后来发现被遮住的地都有一个特点,若(a,b)有gcd(a,b)!= 1,那么就会被遮住。因为斜率k一样,后面的点会被遮住,如果有gcd,那么除一下就会变成gcd = 1的那个点的斜率了。所以问题转化为求gcd不为1有几个点,固定一个点,然后容斥。

    #include<set>
    #include<map>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn = 1000 + 10;
    const int seed = 131;
    const int MOD = 1000000000 + 7;
    const int INF = 0x3f3f3f3f;
    int prime[maxn], p[maxn], pn;
    int a[maxn], an;
    void get(){
        memset(p, 0, sizeof(p));
        pn = 0;
        for(ll i = 2; i < maxn; i++){
            if(!p[i]){
                prime[pn++] = i;
                for(ll j = i * i; j < maxn; j += i)
                    p[j] = 1;
            }
        }
    }
    int main(){
        int n, m;
        int T;
        get();
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n, &m);
            ll ans = m;
            for(int i = 2; i <= n; i++){
                ll cnt = 0;
                //质因数分解
                an = 0;
                int x = i;
                for(int j = 0; prime[j] * prime[j] <= x && j < pn; j++){
                    if(x % prime[j] == 0){
                        a[an++] = prime[j];
                        while(x % prime[j] == 0){
                            x /= prime[j];
                        }
                    }
                }
                if(x > 1) a[an++] = x;
                //求gcd不为1
                for(int j = 1; j < (1 << an); j++){
                    int num = 0;
                    ll val = 1;
                    for(int k = 0;k < an; k++){
                        if(j & (1 << k)){
                            num++;
                            val *= a[k];
                        }
                    }
                    if(num & 1) cnt += m / val;
                    else cnt -= m / val;
                }
                ans += m - cnt;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    最小生成树
    BZOJ3894:文理分科(最大流)(同BZoj3438)
    BZOJ3438:小M的作物 (最大闭合权图->最小割)
    BZOJ 1305:dance跳舞(二分+最大流)
    BZOJ1266:上学路线route (最短路+最小割)
    BZOJ1854:游戏(二分图匹配)
    【PowerOJ1738】最小路径覆盖
    【SPOJ839】Optimal Marks 网络流
    【USACO】AC自动机
    【国家集训队2011】聪聪可可 树分治
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9568783.html
Copyright © 2011-2022 走看看