首页 > 其他分享 >ABC F(500)

ABC F(500)

时间:2024-08-28 11:03:57浏览次数:3  
标签:ABC return int res ll leq ans 500

ABC F(*500)

ABC 364 F - Range Connect MST

Problem Statement

There is a graph with \(N + Q\) vertices, numbered \(1, 2, \ldots, N + Q\). Initially, the graph has no edges.

For this graph, perform the following operation for \(i = 1, 2, \ldots, Q\) in order:

  • For each integer \(j\) satisfying \(L_i \leq j \leq R_i\), add an undirected edge with cost \(C_i\) between vertices \(N + i\) and \(j\).

Determine if the graph is connected after all operations are completed. If it is connected, find the cost of a minimum spanning tree of the graph.

A minimum spanning tree is a spanning tree with the smallest possible cost, and the cost of a spanning tree is the sum of the costs of the edges used in the spanning tree.

Constraints

  • \(1 \leq N, Q \leq 2 \times 10^5\)
  • \(1 \leq L_i \leq R_i \leq N\)
  • \(1 \leq C_i \leq 10^9\)
  • All input values are integers.

思路

首先容易想到按边权排序。我们默认每一次操作至少添加一次,那么我们可以将\(N+1\sim N+Q\)看成已经联通,我们可以初始状态看成\(N+1\)个连通块,目标是使最后只剩下一个联通块。而对于具体的一次操作我们显然需要连接范围内所有联通块。

利用set

注意到每一个连通块连接的点是连续的。我们用set储存每个连通块最小的点的编号,每次操作可以二分快速找到连通块数量。具体细节看代码。

struct node {
  int l, r, c;
  bool operator<(const node& u) const { return c < u.c; }
} a[N];
void solve() {
  int n, q;
  cin >> n >> q;
  set<int> st;
  for (int i = 1; i <= n; ++i) st.insert(i);
  for (int i = 1; i <= q; ++i) cin >> a[i].l >> a[i].r >> a[i].c;
  sort(a + 1, a + 1 + q);
  ll ans = 0;
  for (int i = 1; i <= q; ++i) {
    auto s = st.upper_bound(a[i].l), e = st.upper_bound(a[i].r);
    s--, e--;
    ll cnt = 1;
    if (s != e) {
      s++;
      while (s != e) {
        auto it = ++s;
        s--;
        st.erase(s);
        s = it;
        cnt++;
      }
      cnt++;
      st.erase(e);
    }
    ans += cnt * a[i].c;
  }
  if (st.size() > 1) ans = -1;
  cout << ans;
}

利用并查集

原理和用set类似。

代码

struct node {
  int l, r, c;
  bool operator<(const node& u) const { return c < u.c; }
} a[N];
int pre[N];
inline int root(int x) { return pre[x] = (pre[x] == x ? x : root(pre[x])); }
void solve() {
  int n, q;
  cin >> n >> q;
  for (int i = 1; i <= n; ++i) pre[i] = i;
  for (int i = 1; i <= q; ++i) cin >> a[i].l >> a[i].r >> a[i].c;
  sort(a + 1, a + 1 + q);
  ll ans = 0;
  for (int i = 1; i <= q; ++i) {
    auto [l, r, c] = a[i];
    ans += c;
    while (root(l) != root(r)) ans += c, pre[root(r)] = root(r) - 1;
  }
  if (root(1) != root(n)) ans = -1;
  cout << ans;
}

利用线段树

我们维护一个数组\(t\),若\(i\)与\(i+1\)联通,则为0否则为1。那么,\([l,r]\)的联通块数量为\([l,r)\)的和加1。证明很容易,不多赘述。

struct node {
  int l, r, c;
  bool operator<(const node& u) const { return c < u.c; }
} a[N];
#define ls p << 1
#define rs p << 1 | 1
struct tree {
  ll l, r, s, lz, mlz;
} t[N << 2];

inline ll mo(ll x) { return (x + mod) % mod; }

inline void push_up(ll p) { t[p].s = mo(t[ls].s + t[rs].s); }

void update(ll p, ll k, ll x) {
  t[p].s = mo(mo(t[p].s * k) + mo(x * (t[p].r - t[p].l + 1)));
  t[p].mlz = mo(t[p].mlz * k);
  t[p].lz = mo(mo(t[p].lz * k) + x);
}

void push_down(ll p) {
  if (t[p].lz == 0 && t[p].mlz == 1) return;
  update(ls, t[p].mlz, t[p].lz);
  update(rs, t[p].mlz, t[p].lz);
  t[p].lz = 0, t[p].mlz = 1;
}
void build(ll p, ll l, ll r) {
  t[p] = {l, r, 0, 0, 1};
  if (l == r) {
    t[p].s = 1;
    return;
  }
  ll mid = l + r >> 1;
  build(ls, l, mid);
  build(rs, mid + 1, r);
  push_up(p);
}

void modify(ll p, ll l, ll r, ll k, ll x) {
  if (l > r) return;
  if (l <= t[p].l and r >= t[p].r) {
    update(p, k, x);
    return;
  }
  push_down(p);
  if (l <= t[ls].r) modify(ls, l, r, k, x);
  if (r >= t[rs].l) modify(rs, l, r, k, x);
  push_up(p);
}
ll query(ll p, ll l, ll r) {
  if (l > r) return 0;
  if (l <= t[p].l and r >= t[p].r) return t[p].s;

  push_down(p);
  ll res = 0;
  if (l <= t[ls].r) res = mo(res + query(ls, l, r));
  if (r >= t[rs].l) res = mo(res + query(rs, l, r));
  return res;
}

void solve() {
  int n, q;
  cin >> n >> q;
  for (int i = 1; i <= q; ++i) cin >> a[i].l >> a[i].r >> a[i].c;
  sort(a + 1, a + 1 + q);
  build(1, 1, n - 1);
  ll ans = 0;
  for (int i = 1; i <= q; ++i) {
    auto [l, r, c] = a[i];
    ans += c * (1 + query(1, l, r - 1));
    modify(1, l, r - 1, 0, 0);
  }
  if (query(1, 1, n - 1)) ans = -1;
  cout << ans;
}

ABC 361 F - x = a^b

Problem Statement

How many integers \(x\) between \(1\) and \(N\), inclusive, can be expressed as \(x = a^b\) using some positive integer \(a\) and a positive integer \(b\) not less than \(2\)?

Constraints

  • All input values are integers.
  • \(1 \le N \le 10^{18}\)

方法一

答案为

\[\sum_{i=1}^{n} [i可以被表示为a^b] \]

注意到,一个数如果可以表示为\(a^{kb}\)那么它一定也可以被表示为\(a^b\),那么我们可以先只考虑\(b\)为质数。我们先排除1,注意到\(2^{60}>10^{18}\),那么我们可以只考虑\(60\)以内的质数,只有17个。设其为\(p_i\),我们令\(A_i\)表示可以表示为\(a^{p_i}\)的个数。那么答案显然为

\[|A_1\cup A_2\cup \cdots\cup A_n| \]

利用容斥原理显然可以解决。

但是由于精度问题,我们不能直接pow(n,1.0/x)解\(\sqrt[x]{n}\),或者解出来后在向左右分别枚举一下,python是可以解决的。但是c++不行。

但是因为这几个质数乘积要小于\(60\)。实际需要解的数量是很少的,且\(x>2\)从1枚举也只需要\(1e6\),因此可以直接枚举。而\(x=2\)时,也不能用sqrt(),得用sqrtl()

int pri[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59};

int nr(ll n, ll r) {
  if (r == 2) return sqrtl(n);
  for (int i = 2;; ++i) {
    if (pow(i, r) > n) {
      return i - 1;
    }
  }
}
void solve() {
  ll n;
  cin >> n;
  int up = 0;
  for (; up < 17; ++up) {
    if (1ll << pri[up] > n) break;
  }
  ll ans = 0;
  for (int i = 1; i < (1ll << up); ++i) {
    int cnt = 0, r = 1;
    for (int j = 0; j < 17; ++j) {
      if (i >> j & 1) cnt++, r *= pri[j];
      if (r >= 60) break;
    }
    if (r < 60) {
      ans += (cnt % 2 == 0 ? -1 : 1) * (nr(n, r) - 1);
    }
  }
  cout << ans + 1;
}

方法二

不妨设\(f(x)\)为\(2\sim n\)仅可表示为\(a^x\)的个数,\(g(x)\)为可以表示为\(a^x\)的个数。

那么显然有

\[f(x)=g(x)-f(2x)-f(3x)\cdots \]

从后向前递推即可。

到这里发现,前面的代码能过是运气好。因为pow还是会错。参考答案可以自己写个pow函数。

ll safe_pow(ll a, ll b) {
  ll res = 1;
  for (ll i = 0; i < b; i++) {
    double dres = res;
    dres *= a;
    if (dres > 2e18) {
      return 2e18;
    }
    res *= a;
  }
  return res;
}

int nr(ll n, ll r) {
  if (r == 2) return sqrtl(n);
  for (int i = 2;; ++i) {
    if (safe_pow(i, r) > n) {
      return i - 1;
    }
  }
}
int f[100], g[100];
void solve() {
  ll n;
  cin >> n;
  ll ans = 1;
  for (int i = 2; i <= 60; ++i) g[i] = nr(n, i) - 1;
  for (int x = 60; x >= 2; --x) {
    f[x] = g[x];
    for (int k = 2; k * x <= 60; ++k) f[x] -= f[k * x];
    ans += f[x];
  }
  cout << ans;
}

我们也可以用二分来替换开根运算,保证精度。但是懒得写

标签:ABC,return,int,res,ll,leq,ans,500
From: https://www.cnblogs.com/0d00/p/18384190

相关文章

  • [ABC367G] Sum of (XOR^K or 0)
    MyBlogs[ABC367G]Sumof(XOR^Kor0)考虑求出\(ans_i\)表示选了\(m\)的倍数个数,异或和是\(i\)的方案数再统计答案。先考虑\(m=1\)怎么做。相当于是\(ans_i=[x^i]\prod_j(x^0+x^{a_j})\),这里的乘法是异或卷积。如果直接xor-FWT复杂度不如暴力。令\(F_i(x)\)表......
  • ABC368
     D树从叶子到根,对于某个点,如果其子树不存在需要的点,那么这个点和它的父亲所连的边,自然不需要,否则需要。有一个问题,比如需要点2、4、5,那么点1和点2所连的边也算进去了。实际上,到了它们的LCS(最大公共祖先)后,这些边就不用算了。用一个变量统计当前遍历过多少需要的点,如果所有需要......
  • 高盛资金流专家:预计标普500本周将创新高,引发FOMO
    内容提要ScottRubner最新表示,企业回购和系统性基金的强劲资金流入,应该会推动标普500指数在本周创下历史新高,从而进一步增加投资者的害怕错过(FOMO)情绪。不过,三周后股票需求可能会耗尽,这意味着美股市场可能会再次下跌。本季度英伟达的盈利门槛比前几个季度低得多。文章正文研......
  • 记一场 ABC364
    于洛谷专栏获得更差的阅读体验。于CSDN获得更一般的阅读体验。赛时ACABCD,赛后补出了E。由于比赛在一个月前,本来已经忘记这场比赛了,直到我看到了:(来自一位超厉害的小学同学神犇)\(364\)?很近的比赛啊,我打过吗?似乎打过?打开题目一看:这不就是斯坦纳树板题吗?但我为什么没印象?......
  • 网站提示500.12 服务器错误:Web 服务器上的应用程序正在重新启动怎么办
    当网站提示 500.12InternalServerError 并指出“Web服务器上的应用程序正在重新启动”时,这通常意味着IIS(InternetInformationServices)正在重新启动一个ASP.NET应用程序池。这种情况通常是由于应用程序池的配置问题、应用程序错误或资源问题引起的。以下是解决 500......
  • 网站提示500.11 服务器错误:Web 服务器上的应用程序正在关闭怎么办
    当网站提示 500.11InternalServerError 并指出“Web服务器上的应用程序正在关闭”时,这通常意味着应用程序池(ApplicationPool)在IIS(InternetInformationServices)服务器上已停止运行或正在重启过程中。这种情况通常发生在ASP.NET应用程序中。以下是解决 500.11Internal......
  • 网站提示500.16 服务器错误:UNC 授权凭据不正确怎么办
    当网站提示 500.16InternalServerError 并指出“UNC授权凭据不正确”时,这通常意味着IIS(InternetInformationServices)服务器在尝试访问一个网络共享资源(UNC路径)时遇到了授权问题。这类错误通常与服务器访问网络资源所需的凭据有关。以下是解决 500.16Internal......
  • 网站提示500.19 服务器错误:该文件的数据在配置数据库中配置不正确怎么办
    当网站提示 500.19InternalServerError 并指出“该文件的数据在配置数据库中配置不正确”时,这通常意味着IIS(InternetInformationServices)服务器上的配置文件(如 web.config)存在问题。这类错误通常与配置文件的格式、权限或内容有关。以下是解决 500.19InternalServ......
  • 网站提示500.14 服务器错误:服务器上的无效应用程序配置怎么办
    当网站提示 500.14InternalServerError 并指出“服务器上的无效应用程序配置”时,这通常意味着IIS(InternetInformationServices)服务器上的应用程序配置存在问题。这种情况可能是由于配置文件错误、应用程序池配置不当、应用程序配置错误等原因引起的。以下是解决 500.......
  • 网站提示500.15 服务器错误:不允许直接请求 GLOBAL.ASA怎么办
    当网站提示 500.15InternalServerError 并指出“不允许直接请求GLOBAL.ASA”时,这通常意味着IIS(InternetInformationServices)服务器接收到一个直接指向 GLOBAL.ASA 文件的请求。GLOBAL.ASA 是一个特殊的文件,在ASP(ActiveServerPages)应用程序中用于定义全局事......