好题选讲3

G HUGE GCD SPOJ18202

给定两个长度分别为 \(n\)\(m\) 的序列 \(a\)\(b\),求 \(\gcd(\prod\limits^n_{i = 1}a_i, \prod\limits^m_{i = 1}b_i)\)\(n, m \leq 1000\)

对每个 \(a\ O(n)\) 算贡献即可。时间复杂度 \(O(n^2)\)

Code
// STOOOOOOOOOOOOOOOOOOOOOOOOO hzt CCCCCCCCCCCCCCCCCCCCCCCORZ
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 1000 + 1, kP = 1e9;

int n, m;
int a[kN], b[kN];
int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  cin >> m;
  for (int i = 1; i <= m; i++) {
    cin >> b[i];
  }
  int ans = 1, t = 0;
  for (int i = 1; i <= n; i++) {
    for (int j = 1, g; j <= m; j++) {
      g = __gcd(a[i], b[j]);
      a[i] /= g, b[j] /= g;
      t |= (1ll * ans * g >= kP);
      ans = 1ll * ans * g % kP;
    }
  }
  if (t) {
    string s;
    for (int i = 1; i <= 9; i++) {
      s += ans % 10 + '0', ans /= 10;
    }
    reverse(s.begin(), s.end());
    cout << s << '\n';
  } else {
    cout << ans << '\n';
  }
  return 0;
}

H MUH and Cube Walls CF471D

给两堵墙 \(a,b\),问 \(a\) 墙中与 \(b\) 墙顶部形状相同的区间有多少个。\(|a|,|b|\leq 2\times10^5, 1\leq a_i, b_i\leq 10^9\)

这个形状相同不考虑高度,所以可以差分消除高度对区间形态判断的影响。然后字符串匹配即可。时间复杂度 \(O(n\log n)\)

Code
// STOOOOOOOOOOOOOOOOOOOOOOOOO hzt CCCCCCCCCCCCCCCCCCCCCCCORZ
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 2e5 + 1;

int n, m;
int a[kN], b[2 * kN];
int f[kN];
int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> m;
  if (m == 1) {
    cout << n << '\n';
    return 0;
  }
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1; i <= m; i++) {
    cin >> b[i];
  }
  for (int i = 1; i < n; i++) {
    a[i] -= a[i + 1];
    b[i] -= b[i + 1];
  }
  b[m] = -2e9, n--;
  copy_n(a + 1, n, b + m + 1);
  int ans = 0;
  for (int i = 2, j = 0; i <= n + m; i++) {
    for (; j && b[j + 1] != b[i]; j = f[j]) {
    }
    b[j + 1] == b[i] && j++;
    f[i] = j;
    j == m - 1 && ans++;
  }
  cout << ans << '\n';
  return 0;
}

I Increase Sequence CF466D

给定一个长度为 \(n\) 的序列,可以对任意个区间 \([l, r]\) 内的数 \(+1\),同一个点不能同时作为两个区间的左端点或右端点。问使这个序列每个数全部变为 \(h\) 的方案数\(\mod 10^9+7\)\(1\leq n, h\leq 2000, 0\leq a_i \leq 2000\)

变为 \(h\) 很烦,不如直接让 \(a_i = h - a_i\) 然后区间 \(-1\) 序列消为 \(0\)
区间 \(-1\) 也很烦,不如直接将 \(a\) 差分为 \(d\) 把区间问题转化为每次一个点 \(-1\) 后面一个点 \(+1\) 序列消为 \(0\)。注意要差分要补上第 \(n+1\) 项。(因为这项是有意义的,区间减到最后一个数他就要加的)

什么情况无解?当差分后 \(\exist 1\leq i \leq n + 1, |d_i| > 1\),因为不能同时减两次,所以无解。不存在其他无解条件。

于是分类讨论 \(d_i\) 的值。令前 \(i - 1\) 项有 \(cnt\) 个区间没有遇到右端点以闭合,则:

  • \(d_i = 0\),在 \(i\) 上,可以什么也不干(\(1\) 种方案),也可以同时作为左端点和右端点(\(cnt\) 种方案),共 \(cnt+1\) 种。
  • \(d_i = 1\),在 \(i\) 上,只能新开一个区间,方案数不变,cnt++
  • \(d_i = -1\),在 \(i\) 上,只能作为右端点让一个区间闭合(\(cnt\) 种方案),同时 cnt--

做完了,时间复杂度 \(O(n)\)。不知道这个数据范围有没有骗到人。

Code
// STOOOOOOOOOOOOOOOOOOOOOOOOO hzt CCCCCCCCCCCCCCCCCCCCCCCORZ
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 2e3 + 2, kP = 1e9 + 7;

int n, h;
int a[kN];
int main() {
  cin.tie(0)->sync_with_stdio(0);
  cin >> n >> h;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    a[i] = h - a[i];
  }
  for (int i = n + 1; i >= 1; i--) {
    a[i] -= a[i - 1];
    if (abs(a[i]) > 1) {
      cout << "0\n";
      return 0;
    }
  }
  int cnt = 0, ans = 1;
  for (int i = 1; i <= n; i++) {
    if (a[i] == 1) {
      cnt++;
    } else if (a[i] == 0) {
      ans = ans * (cnt + 1ll) % kP;
    } else {
      ans = 1ll * ans * cnt % kP, cnt--;
    }
  }
  cout << ans << '\n';
  return 0;
}

J Equation ARC158D

给定一个不小于 \(5\) 的质数 \(p\) 和一个正整数 \(n\),求一个三元组 \((a,b,c)\) 使 \((a+b+c)(a^n+b^n+c^n)(a^{2n}+b^{2n}+c^{2n})\equiv a^{3n}+b^{3n}+c^{3n}\ (mod\ p)\)\(1\leq a<b<c<p, n, p\leq 10^9\)\(10^5\) 组数据。

随便一个三元组。只要同余式两边不是 \(0\),总存在一个数 \(k\) 使得

\[(a+b+c)(a^n+b^n+c^n)(a^{2n}+b^{2n}+c^{2n})\equiv k(a^{3n}+b^{3n}+c^{3n})\ (mod\ p) \]

因为可以直接除。
两边同时除以 \(k^{3n+1}\)

\[(\frac{a}{k}+\frac{b}{k}+\frac{c}{k})[(\frac{a}{k})^n+(\frac{b}{k})^n+(\frac{c}{k})^n][(\frac{a}{k})^{2n}+(\frac{b}{k})^{2n}+(\frac{c}{k})^{2n}]\equiv (\frac{a}{k})^{3n}+(\frac{b}{k})^{3n}+(\frac{c}{k})^{3n}\ (mod\ p) \]

于是获得了一组解。但是有可能出现两个数相同得情况,需要多随几遍。

Code

代码太丑了,可以看 bykem 的。

posted @ 2024-04-18 16:35  Lightwhite  阅读(16)  评论(0编辑  收藏  举报