[COCI2022-2023#3] Bomboni

这题放普及组 t4 刚刚好。

的做法相信大家都能做出来,这里就不讲了。

一个数的因数个数肯定不会太多。查阅经典表格发现 范围内因数最多的数,其因子只有 个。

若两个数相乘后是否能被 整除,只和这个两个数与 有关,而与 互质的部分不会发挥作用,对后续计算不会产生影响。

综上,设已经走过的路径上所有数的乘积为 。我们设计 的第三个维度 为满足 的方案个数。最后的答案即

using mi = modint<998244353>;
int main(void) {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  size_t n;
  ui h;
  fin >> n >> h;
  vector<ui> d;
  array<size_t, size_t(1e6) + 1> rd;
  rd.fill(~0);
  for (ui i = 1; i <= h; ++i)
    if (h % i == 0) rd[i] = d.size(), d.emplace_back(i);
  vector<ui> gcd(h);
  for (ui i = 0; i < h; ++i) gcd[i] = rd[__gcd(i, h)];
  vector<vector<ui>> mp(n, vector<ui>(n));
  for (auto& i : mp)
    for (auto& j : i) {
      int x;
      fin >> x;
      j = x;
    }
  auto calc = [&d, h, &gcd](vector<mi> const& f, ui v) {
    if (!~v) return vector<mi>(d.size());
    vector<mi> g(d.size());
    for (size_t i = 0; i < d.size(); ++i) g[gcd[(uli)d[i] * v % h]] += f[i];
    return g;
  };
  auto merge = [](vector<mi> f, vector<mi> const& g) {
    for (size_t i = 0; i < f.size(); ++i) f[i] += g[i];
    return f;
  };
  vector<vector<vector<mi>>> dp(n, vector<vector<mi>>(n));
  dp[0][0] = vector<mi>(d.size()), dp[0][0][gcd[mp[0][0] % h]] = 1;
  for (size_t i = 1; i < n; ++i) dp[0][i] = calc(dp[0][i - 1], mp[0][i]);
  for (size_t i = 1; i < n; ++i) dp[i][0] = calc(dp[i - 1][0], mp[i][0]);
  for (size_t i = 1; i < n; ++i)
    for (size_t j = 1; j < n; ++j)
      dp[i][j] =
          merge(calc(dp[i][j - 1], mp[i][j]), calc(dp[i - 1][j], mp[i][j]));
  fout << dp.back().back().back();
  return 0;
}
posted @ 2024-10-23 09:10  MrPython  阅读(5)  评论(0)    收藏  举报  来源