zoukankan      html  css  js  c++  java
  • Codeforces 1220D

    1. 正确理解题意:

    • 简述该题:

    给定两个集合,(B={x,y,dots}), (Z={整数集})

    如果集合 (Z) 中的两个元素 (i, j) 之差在集合 (B) 中,则有一条连接 (i, j) 的边。

    现在要从集合 (B) 中删去一些元素,使得边所连成的图是一个二分图。

    使得删去的元素尽可能少。

    2. 思路及简单证明:

    首先判断是不是二分图可以看图中是否有奇环

    考虑一个特殊的整数 (0)

    如果集合 (B) 中一个数 (a) 减去 (0) 所得还是 (a)。所以 (a)(0) 之间有一条边。

    (a) 的因数 (frac{a}{2}) 也在集合 %B% 中,那么 (0)(a)(frac{a}{2}) 之间形成一个奇环。

    因此我们在选中 (a) 后要将其倍数和因数全部删除。

    也就是说在 (0)(a) 之间存在一个步数,步长是一个素数。我们走了 (x) 步从 (0)(a)

    同理,我们也可以通过不同的步长和步数走到一个位置。现在假设两次都走到了 (lcm)

    只有我们两边步数相同时,链接起来才不是奇环。(链接的地方在 (lcm)

    3. 实现:

    (mathcal{AC}) 代码:

    #include <iostream>
    #include <cstdio>
    #include <map>
    #include <algorithm>
    
    #define int long long
    #define ri register int
    using namespace std;
    int n, a[200010], cnt[200010];
    map<int,int> mp;
    map<int,int>::iterator ans;
    
    signed main()
    {
      scanf("%lld", &n);
      for (ri i=1; i<=n; i++) {
        scanf("%lld", &a[i]);
        int x=a[i];
        while (x && x%2==0) {
          cnt[i]++;
          x/=2;
        }
        mp[cnt[i]]++;
      }
      int ansval=0;
      for (map<int,int>::iterator it=mp.begin(); it!=mp.end(); ++it) {
        if ((*it).second>ansval) {
          ans=it;
          ansval=(*it).second;
        }
      }
      printf("%lld
    ", n-(*ans).second);
      for (ri i=1; i<=n; i++) {
        if (cnt[i]!=(*ans).first) {
          printf("%lld
    ", a[i]);
        }
      }
      return 0;
    }
    
    

    参考博客:

    https://www.cnblogs.com/luowentao/p/11550190.html

    https://www.cnblogs.com/BakaCirno/p/11550454.html

  • 相关阅读:
    Dubbo探索(七)
    Dubbo探索(六)
    Dubbo探索(五)
    Dubbo探索(四)
    Redis主节点内存占用过高
    修改RedHat 7.2 进程最大句柄数限制
    Linux 数据分析常用 shell命令
    流处理
    根域名服务器
    并发与并行(concurrency vs parallesim)
  • 原文地址:https://www.cnblogs.com/Vty66CCFF/p/12333806.html
Copyright © 2011-2022 走看看