首页 > 其他分享 >Codeforces Round #828 (Div. 3)

Codeforces Round #828 (Div. 3)

时间:2022-10-17 01:11:05浏览次数:76  
标签:std return factors int Codeforces int64 828 using Div

E2. Divisible Numbers (hard version)

用 pollard rho 跑出 \(ab\) 的质因数分解,然后 dfs 枚举 \(ab\) 的所有因子对 \(x, y\),如果存在 \(k_1, k_2\) 使得 \(a < k_1x \le c\) 且 \(b < k_2y \le d\),那么 \(k_1x\) 和 \(k_2y\)就是一个可行解。

复杂度没算,问就是能过。

AC代码
// Problem: E2. Divisible Numbers (hard version)
// Contest: Codeforces - Codeforces Round  #828 (Div. 3)
// URL: https://codeforces.com/contest/1744/problem/E2
// Memory Limit: 256 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO                       \
  std::ios::sync_with_stdio(false); \
  std::cin.tie(0);                  \
  std::cout.tie(0);

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#define ASSERT(x) ;
#define serialize() std::string("")
#endif

using i64 = int64_t;
using u64 = uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;

void Initialize();
void SolveCase(int Case);

int main(int argc, char* argv[]) {
  CPPIO;

  Initialize();

  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    SolveCase(t);
  }
  return 0;
}

void Initialize() {}

namespace PollardRho {

/**
 * @TODO: __int128_t is ugly, try optimize it.
 */

static std::mt19937_64 rng_(
    std::chrono::steady_clock::now().time_since_epoch().count());

inline int64_t Rand(int64_t l, int64_t r) {
  return l + rng_() % (r - l + 1);
}

inline int64_t Add(int64_t a, int64_t b, int64_t mod) {
  return ((__int128_t)a + b) % mod;
}

inline int64_t Substract(int64_t a, int64_t b, int64_t mod) {
  return (((__int128_t)a - b) % mod + mod) % mod;
}

inline int64_t Multiply(int64_t a, int64_t b, int64_t mod) {
  return (__int128_t)a * b % mod;
}

inline int64_t Power(int64_t a, int64_t b, int64_t mod) {
  int64_t r = 1;
  while (b) {
    if (b & 1)
      r = Multiply(r, a, mod);
    a = Multiply(a, a, mod);
    b >>= 1;
  }
  return r;
}

// Time Complexity: $O(k \log^{3} n)$
bool MillerRabinTest(int64_t n) {
  // Strong enough for $n < 2^64$, see https://oeis.org/A014233.
  constexpr static int kTestRounds = 12;
  constexpr static int kTestBase[kTestRounds] = {2,  3,  5,  7,  11, 13,
                                                 17, 19, 23, 29, 31, 37};

  if (n <= kTestBase[kTestRounds - 1]) {
    return *std::lower_bound(kTestBase, kTestBase + kTestRounds, n) == n;
  }

  int64_t d = n - 1, r = 0;
  while (d % 2 == 0) {
    d >>= 1;
    r = r + 1;
  }

  for (int round = 0; round < kTestRounds; ++round) {
    int64_t a = kTestBase[round];

    // Fermet primality test.
    int64_t x = Power(a, d, n);
    if (x == 1 || x == n - 1)
      continue;

    // Witness primality test.
    for (int i = 0; i < r - 1; ++i) {
      x = Multiply(x, x, n);
      if (x == n - 1)
        break;
    }
    if (x != n - 1)
      return false;
  }

  return true;
}

int64_t Rho(int64_t n) {
  // Can not factor 4 because the faster step gap is 2.
  if (n == 4)
    return 2;

  const static int kMaxStepSize = 1 << 7;

  int64_t c;
  std::function<int64_t(int64_t)> f = [&n, &c](int64_t x) {
    return Add(Multiply(x, x, n), c, n);
  };

  // Since n is not a prime, there must be a non-trivial factor of n.
  for (;;) {
    /**
     * Brent's cycle finding method, and replace k gcd steps with k - 1
     * multiplications modulo n and a single gcd. reference:
     * https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm#Variants.
     */
    c = Rand(3, n - 1);

    int64_t x = Rand(0, n - 1);
    int64_t t = f(x), r = f(t);
    int64_t goal = 1, curr = 1;
    int64_t d1, d2 = 1;
    while (t != r) {
      d1 = Multiply(d2, std::abs(r - t), n);
      if (d1 == 0) {
        break;
      } else {
        d2 = d1;
      }

      if (curr % kMaxStepSize == 0) {
        int64_t d = std::gcd(d2, n);
        if (d != 1 && d != n)
          return d;
      }

      if (curr == goal) {
        int64_t d = std::gcd(d2, n);
        if (d != 1 && d != n)
          return d;

        t = r;
        goal = goal * 2;
        curr = 0;
      }

      r = f(r);
      ++curr;
    }
  }
}

std::vector<std::pair<int64_t, int64_t>> Factor(int64_t n) {
  std::vector<std::pair<int64_t, int64_t>> factors;
  std::function<void(int64_t)> factor = [&](int64_t n) {
    if (n < 2)
      return;

    if (MillerRabinTest(n)) {
      factors.push_back({n, 0});
    } else {
      int64_t x = Rho(n);
      while (n % x == 0)
        n /= x;
      factor(x);
      factor(n);
    }
  };
  factor(n);
  std::sort(factors.begin(), factors.end());
  factors.erase(std::unique(factors.begin(), factors.end()), factors.end());
  for (auto& [p, e] : factors) {
    while (n % p == 0) {
      ++e;
      n /= p;
    }
  }
  return factors;
}

};  // namespace PollardRho

std::mt19937 rng(time(0));
int rnd(int l, int r) {
  return l + rng() % (r - l + 1);
}

void SolveCase(int Case) {
  int a, b, c, d;
  std::cin >> a >> b >> c >> d;
  // a = rnd(1, 1e8), c = rnd(a + 1, 1e9);
  // b = rnd(1, 1e8), d = rnd(a + 1, 1e9);

  i64 ab = i64(1) * a * b;
  if (ab == 1) {
    std::cout << c << " " << d << "\n";
    return;
  }

  auto pe = PollardRho::Factor(ab);
  // logd(pe);

  int rx = -1, ry = -1;
  auto check = [&](i64 x, i64 y) {
    i64 nx = c / x * x;
    i64 ny = d / y * y;
    if (nx > a && ny > b) {
      rx = nx;
      ry = ny;
      return;
    }
  };

  std::function<void(int, i64)> dfs = [&](int p, i64 x) {
    if (rx != -1)
      return;

    check(x, ab / x);
    check(ab / x, x);

    if (p == pe.size())
      return;

    i64 y = 1;
    for (int i = 0; i <= pe[p].second; ++i) {
      dfs(p + 1, x * y);
      y = y * pe[p].first;
    }
  };
  dfs(0, 1);

  if (rx != -1) {
    i64 xy = i64(1) * rx * ry;
    assert(a < rx && rx <= c);
    assert(b < ry && ry <= d);
    assert(xy % ab == 0);
  }

  std::cout << rx << " " << ry << "\n";
}

F. MEX vs MED

观察:\(\operatorname{mex}(p_l, p_{l + 1}, \dots, p_r) > \operatorname{med}(p_l, p_{l + 1}, \dots, p_r)\) 等价于 \(0, 1, \dots, \lfloor \frac{r - l}{2} \rfloor\) 都位于 \([l, r]\)。

根据观察可以推出,长度为 \(x\) 的区间要想符合答案,那么必须要有 \(0, 1, 2, \dots, \lfloor \frac{x - 1}{2} \rfloor\) 都位于区间内,即 \(0, 1, 2, \dots, x\) 仅对长度为 \(2x + 1\) 和长度为 \(2x + 2\) 的区间有贡献。

然后就是简单模拟了,即依次枚举\(x\),计算出包含 \(0, 1, 2, \dots, x\) 的极小区间 \([l, r]\),然后看有多少个长度为 \(2x + 1\) 的区间和长度为 \(2x + 2\) 包含 \([l, r]\).

AC代码
// Problem: F. MEX vs MED
// Contest: Codeforces - Codeforces Round  #828 (Div. 3)
// URL: https://codeforces.com/contest/1744/problem/F
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO                       \
  std::ios::sync_with_stdio(false); \
  std::cin.tie(0);                  \
  std::cout.tie(0);

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#define ASSERT(x) ;
#define serialize() std::string("")
#endif

using i64 = int64_t;
using u64 = uint64_t;
using i128 = __int128_t;
using u128 = __uint128_t;

void Initialize();
void SolveCase(int Case);

int main(int argc, char* argv[]) {
  CPPIO;

  Initialize();

  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    SolveCase(t);
  }
  return 0;
}

void Initialize() {}

void SolveCase(int Case) {
  int n;
  std::cin >> n;

  std::vector<int> a(n), b(n);
  for (int i = 0; i < n; ++i) {
    std::cin >> a[i];
    b[a[i]] = i;
  }

  auto calc = [&](int l, int r, int x) -> int {
    logd(l, r, x);
    int y = r - l + 1;
    if (x < y)
      return 0;

    int right_bound = std::min(l, n - 1 - x + 1);
    int left_bound = std::max(0, r - x + 1);
    logd(l, r, x, right_bound, left_bound);
    return right_bound - left_bound + 1;
  };

  i64 ans = 0;
  int l = n, r = -1;
  for (int i = 0; 2 * i + 1 <= n; ++i) {
    l = std::min(l, b[i]);
    r = std::max(r, b[i]);

    ans += calc(l, r, 2 * i + 1);
    if (2 * i + 2 <= n)
      ans += calc(l, r, 2 * i + 2);
  }
  std::cout << ans << "\n";
}

标签:std,return,factors,int,Codeforces,int64,828,using,Div
From: https://www.cnblogs.com/zengzk/p/16797740.html

相关文章

  • Codeforces Round #748 (Div. 3) E
    E.GardenerandTree显然我们对于每一个叶节点是度数为1的我们如果删除外层叶节点的时候显然也要改变与他与他连接的节点的度数而只有可以能在这些节点里诞生新的叶节......
  • Codeforces Round #752 B
    B.ModerateModularMode先列式子n=k1x+by=k2n+b我们把第二个式子n单独提出来(y-b)/k2=k1x+by=k1k2x+(k2+1)b因为题中给出xy都是偶数显然我们可以构造k1=1k2=1......
  • [题解] Codeforces Global Round 23 1746 A B C D E1 F 题解
    点我看题求点赞A.Maxmina首先序列全0的情况肯定是NO。否则,如果\(k\ge3\),则在序列中随便找一个1,把他左边和右边分别用第一种操作不断缩,直到序列长度为k为止,最后用一次2......
  • Codeforces Global Round 23
    A.Maxmina显然结果全为0时,结果为NO,若有1,我们通过操作1使长度变为k,里面包含至少1,通过操作2,结果即为YES1#include<bits/stdc++.h>2usingnamespacestd;3consti......
  • Codeforces Global Round 23题解
    T1link大水题,不想说最后一定可以把一个序列消成长度为\(k\)的带一序列,前提是其原来就有一所以贪心就是如果有一,就行,反之不行codeT2linkwssb,考试的时候居然想了大......
  • Codeforces Global Round 23 (A-E1)个人题解
    A-Maxmina给定一个01串,我们可以将k个数变为他们的最大值(k个数变成1个数),或者将相邻的两个数变为他们的最小值(2个数变成1个数),询问是否可以将这个01串变成仅含有一个1的......
  • Codeforces Global Round 23 题解
    ContestLink我是智障。A.MaxminaProblemLink显然当数组中全是\(0\)的时候,最后不可能变成\(1\),因为我们只有相邻取\(\min\)和区间取\(\max\)两种操作,并没有任......
  • Codeforces试题乱做 Part8
    搬机房的第一天.\(\text{[CF1270I]XoronFigures}\)\(\color{red}{\text{[HARD]}}\)为数不多的\(3500\)清新题.观察到这是个二维循环卷积的形式,考虑矩阵刻画.重......
  • Codeforces Global Round 17 C
    C.KeshiIsThrowingaParty我们显然可以二分答案我们的最优解情况就是从小到大的选择要是a[i]>=x-cnt-1(还要减去自身)&&b[i]>=cnt我们就把他算进去这样肯定是最优......
  • [Editorial] Codeforces Contest 878D
    中文题面好题,写篇题解记录一下。首先如果值域是\(\{0,1\}\),那么直接搞一个bitset维护一下。由于只有\(2^k\)中不同的初始取值,所以维护\(2^k\)长度即可。然后考虑值......