• AtCoder Beginner Contest 168 (A~E,E题很有意思)


    比赛链接:Here

    AB水题,

    C - : (Colon)

    时针转过得角度为:(2π imes frac{h + frac m{12}}{12})

    分针转过得角度为:(2π imes frac{m}{60})

    const double pi = acos(-1.0);
    int main() {
        double a, b, h, m;
        cin >> a >> b >> h >> m;
        long double rad = pi * 2 * ((long double)h / 12.0 + ((long double)m / 60.0) / 12.0 - (long double)m / 60.0);
        long double rsq = (long double)(a * a + b * b) - (long double)(2 * a * b) * cosl(rad);
        printf("%20.20Lf
    ", sqrtl(rsq));
        return 0;
    }
    

    D - .. (Double Dots)

    (N)个点 (M) 条边的图,让你在每个点指明一个方向(就是下一个点),使得从每个点出发,沿着点的指定方向走最终能到达点 (1)

    如果可以,输出 yes ,并且给出每个点指明的方向,否则输出 no

    直接反着考虑,从点 (1) 出发的 (BFS)

    const int N = 1e5 + 10;
    vector<ll>e[N];
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int n, m; cin >> n >> m;
        for (int i = 0, u, v; i < m; ++i) {
            cin >> u >> v, u--, v--;
            e[u].push_back(v);
            e[v].push_back(u);
        }
        vector<ll>dis(n, -1);
        queue<ll>q;
        q.push(0), dis[0] = 0;
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int v : e[u]) {
                if (dis[v] == -1) dis[v] = u, q.push(v);
            }
        }
        cout << "Yes
    ";
        for (int i = 1; i < n; ++i) cout << dis[i] + 1 << "
    ";
    }
    

    E - ∙ (Bullet)

    小兔捕获了 (N) 条不同的沙丁鱼,第 (i) 条沙丁鱼的 美味程度香味程度 分别是 (A_i)(B_i)
    她想在这些沙丁鱼中选择 一条 或者 多条 放入冷冻箱;但是必须保证沙丁鱼的选择是合格的

    合格的定义:其中的任意两条沙丁鱼 (i)​ 和 (j)​ 都不满足 (A_i×A_j+B_i×B_j=0)

    小兔想知道有多少种选择沙丁鱼的方法(选择的沙丁鱼的集合相同,算同一种方法),答案对 (1e9+7)​ 取模

    简化题意:

    (N) 个点,每个点给出 (A_i,B_i)

    在一个集合中,不难存在满足 (A_iB_j + A_jB_i = 0) 的点对

    现在问能选出多少这样的集合,注意对 (1e9 + 7) 取模

    数据范围

    • (1le Nle 2e5)
    • (-10^{18}le A_i,B_ile 10^{18})

    [QAQ ]


    需要不满足的式子与 (i)(j) 的关系太大了,不妨化简一下:

    (A_i×A_j+B_i×B_j=0 o A_i imes A_j = -B_i imes B_j o frac{A_i}{B_i}=-frac{B_j}{A_j})

    所以可能有很多点 (frac{A_i}{B_i}) 相等,把他们染成相同的颜色

    然后不能和他们同时出现的颜色就是 (-frac{B_j}{A_j}) ,找出他们即可

    但是注意,这里等式转换的前提是 (A_i ot =0,B_i ot =0)

    所以有四种情况:

    1. (A_i = 0,B_i =0)
    2. (A_i ot =0,B_i =0)
    3. (A_i=0,B_i ot =0)
    4. (A_i ot =0,B_i ot =0)

    其中,
    ①和其他三种都不能在一个集合
    ②和③不能在一个集合
    ④中某些点不能在一个集合
    那么我们直接染色找即可
    还有一个问题

    就是 (frac{A_i}{B_i}) 是一个小数,如果我们用 map 来存有可能精度不够,所以将 (frac{A_i}{B_i}) 转化为分数 (afrac bc) 的三元组 ((a, b, c)) 来记录,还要考虑一下符号,所以用两个 map

    最后我们都找到了后,要考虑计算答案
    对于一种颜色来说,假如它有 (Siz) 各点

    每个点选和不选两种情况,总的就是 (2^{Siz}) 种情况,再减去全都不选的情况,所以最终这个颜色的选法就是 (2^{Siz} - 1)

    然后假如不能和他同时选的另一种颜色是 (rhs[color])

    那么就是三种情况

    • (color)
    • (rhs[color])
    • 都不选

    这样考虑即可

    typedef pair<int, int> pii;
    typedef pair<int, pii> piii;
    const int MAX = 2e5 + 10;
    const ll mod = 1000000007;
    int N;
    ll siz[MAX], rhs[MAX], col, vis[MAX];
    ll f[MAX], num1, num2;
    map<piii, int> mp[2];
    
    inline piii calc(ll x, ll y) {
        x = abs(x), y = abs(y);
        ll gcd = __gcd(x % y, y);
        return piii{x / y, {x % y / gcd, y / gcd}};
    }
    
    int main() {
        scanf("%d", &N);
        f[0] = 1;
        for (int i = 1; i <= N; i++) f[i] = 1ll * f[i - 1] * 2 % mod;
        for (int i = 0; i <= N; i++) f[i] = (f[i] - 1 + mod) % mod;
        ll ans = 0;
        for (int i = 1; i <= N; i++) {
            ll a, b; scanf("%lld%lld", &a, &b);
            if (a == 0 && b == 0) ans++;//a=0,b=0,只能选和不选
            else if (a == 0) num1++;
            else if (b == 0) num2++;
            else {
                piii now = calc(a, b), pre = calc(b, a);//转化为三元组
                int state = 0;//判断符号
                if (1.0 * a / b > 0) state = 1;
                if (!mp[state].count(now)) {
                    mp[state][now] = ++col;
                    if (mp[state ^ 1].count(pre))
                        rhs[col] = mp[state ^ 1][pre], rhs[mp[state ^ 1][pre]] = col;
                }
                siz[mp[state][now]]++;
            }
        }
        ll t = (f[num1] + f[num2] + 1) % mod;//a = 0, b != 0 和 a!=0, b = 0
        for (int i = 1; i <= col; i++)
            if (!vis[i]) {
                vis[i] = 1;
                if (rhs[i]) {
                    vis[rhs[i]] = 1;
                    t = t * ((1ll + (f[siz[i]] + f[siz[rhs[i]]]) % mod) % mod) % mod;
                }
                else t = t * ((1ll + f[siz[i]]) % mod) % mod;
            }
        ans = (ans + t) % mod;
        printf("%lld
    ", (ans - 1 + mod) % mod);
    }
    
    
    

    写法改进

    const int mod = 1e9 + 7;
    ll qpow(ll a, ll b) {
        ll ans = 1;
        for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
        return ans;
    }
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        ll n; cin >> n;
        map<pair<ll, ll>, pair<ll, ll>> m;
        ll ans = 1, P = mod - 1;
        for (int i = 0; i < n; ++i) {
            ll a, b;
            cin >> a >> b;
            if (!a && !b) P += 1;
            else {
                ll g = __gcd(a, b);
                a /= g, b /= g;
                if (b < 0) a = -a, b = -b;
                if (a <= 0) m[ {b, -a}].second++;
                else m[ {a, b}].first ++;
            }
        }
        for (auto u : m) ans = ans * (qpow(2, u.second.first) + qpow(2, u.second.second) - 1 + mod) % mod;
        cout << (ans + P) % mod;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    学生数据增删改查--顺序表
    应用3+2mvc第一次作业
    双色球随机选【代码】
    字符串穷举
    使用nuget发布自己的包
    VS CODE中配置JAVA格式化细节
    反射的理解(含一点xml)
    UdpClient实现udp消息收发
    c#背包问题代码
    利用TcpClient,简单的tcp消息收发
  • 原文地址:https://www.cnblogs.com/RioTian/p/15167020.html
Copyright © 2020-2023  润新知