2024/09/23 模拟赛总结

rk3,\(0+100+30+5=135\)

#A. 依依寺

唐氏分类讨论,赛时写了个记搜爆0了

因为 \(0\) 不会改变取得数的和,所以 \(a\) 可以改为 \(a \bmod 2\)

接下来分类讨论

  • 假设先手取 \(1\),那么后手取 \(2\) 直接输,则一定先取 \(1\),接下来先手取 \(1\) 又输,只能取 \(2\),然后就会循环后手 \(1\),先手 \(2\),后手 \(1\),先手 \(2\dots\)

  • 假设先手取 \(2\),同理接下来会循环后手 \(2\),先手 \(1\),后手 \(2\),先手 \(1\dots\)

\(0\) 可以交换先后手,再进行一次分讨即可

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

int t;
LL a, b, c;

void pr(bool pr) {
  cout << (pr ? "Second" : "First") << '\n';
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  freopen("yiyi.in", "r", stdin);
  freopen("yiyi.out", "w", stdout);
  for (cin >> t; t; t--) {
    cin >> a >> b >> c;
    (a & 1) ? (pr(b ? (b - 1 <= c && c <= b + 1) : (c == 0 || c == 1))) : (pr(b == 1 ? 0 : (b ? c == 0 : c != 1)));
  }
  return 0;
}

#B. 武义寺

赛时用了 1h 把式子推出来了,跑了 \(10^4\) 组拍子,没挂分

考虑打表找规律,令 \(v_i\)\(val(p)=i\) 的方案数,显然不论如何放 \(val\) 一定不等于 \(1\),表格中不存在即没有限制。

\(i=2\) 时:

\(p_2\)
\(1\)

答案为 \((n-1)!\)

\(i=3\) 时:

\(p_2\) 方案数 \(p_3\)
\(n-1\)(除去\(1\)) \(1\)
\(n-2\)(除去\(1,p_3\)) \(2\)

答案为 \([(n-1) + (n-2)](n-2)!\)

\(i=4\) 时:

\(p_2\) 方案数 \(p_3\) 方案数 \(p_4\)
\(n-2\)(除去\(1,p_3\)) \(n-2\)(除去\(1,2\)) \(1\)
\(n-3\)(除去\(1,p_3,p_4\)) \(n-2\)(除去\(1,2\)) \(2\)
\(n-3\)(除去\(1,p_3,p_4\)) \(n-3\)(除去\(1,2,p_4\)) \(3\)

答案为 \([(n-2)^2+(n-2)(n-3)+(n-3)^2](n-3)!\)

\(i=5\) 时:

\(p_2\) 方案数 \(p_3\) 方案数 \(p_4\) 方案数 \(p_5\)
\(n-3\)(除去\(1,p_3,p_4\)) \(n-3\)(除去\(1,2,p_4\)) \(n-3\)(除去\(1,2,3\)) \(1\)
\(n-4\)(除去\(1,p_3,p_4,p_5\)) \(n-3\)(除去\(1,2,p_4\)) \(n-3\)(除去\(1,2,3\)) \(2\)
\(n-4\)(除去\(1,p_3,p_4,p_5\)) \(n-4\)(除去\(1,2,p_4,p_5\)) \(n-3\)(除去\(1,2,3\)) \(3\)
\(n-4\)(除去\(1,p_3,p_4,p_5\)) \(n-4\)(除去\(1,2,p_4,p_5\)) \(n-4\)(除去\(1,2,3,p_5\)) \(4\)

答案为 \([(n-3)^3+(n-3)^2(n-4)+(n-3)(n-4)^2+(n-4)^3](n-4)!\)

到这里已经大概看出规律了,\(n-i+2,n-i+1\) 形成了一个阶梯。

这样就可以列出式子:\(v_i=\displaystyle\sum_{j=0}^{i-2}(n-i+1)^j(n-i+2)^{i-j-2}\)

但是这样还是 \(O(n^2)\) 的做法,考虑 \((n-i+1)+1=n-i+2\),令 \(a=n-i+1\)

证明 \(\displaystyle\sum_{i=0}^{k}a^i(a+1)^{k-i}=(a+1)^{k+1}-a^{k+1}\)

这是一个不严谨的证明,因为我们再次使用了找规律
考虑当 \(k=5\) 时,我们展开和式:
\(\,\,\,\,\,a^5+5a^4+10a^3+10a^2+5a+1\)
\(+a^5+4a^4+6a^3\,\,\,+4a^2\,\,\,+a\)
\(+a^5+3a^4+3a^3\,\,\,+1a^2\,\,\,\)
\(+a^5+2a^4+a^3\,\,\,\)
\(+a^5+a^4\)
\(+a^5\)
按列相加得到 \(6a^5+15a^4+20a^3+15a^2+6a+1\),通过补项得到:\(a^6+6a^5+15a^4+20a^3+15a^2+6a+1-a^6=(a+1)^6-a^6\)

\[\texttt{Q.E.D.} \]

直接按式子模拟即可,注意 \(k=i-2\),由于是期望,最后要除掉 \(\frac{i}{n!}\)

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const LL kP = 998244353;
const int kMaxN = 1e6 + 5;

LL n, f[kMaxN], ans, cnt;

LL P(LL x, LL y, LL ret = 1) {
  for (; y; (y & 1) && ((ret *= x) %= kP), (x *= x) %= kP, y >>= 1) {
  }
  return ret;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), f[0] = 1;
  freopen("wuyi.in", "r", stdin);
  freopen("wuyi.out", "w", stdout);
  for (int i = 1; i < kMaxN; i++) {
    f[i] = f[i - 1] * i % kP;
  }
  cin >> n;
  for (LL i = 2, tmp = 0; i <= n + 1; i++, tmp = 0) {
    cnt = f[n - i + 1] * i % kP; 
    LL l = n - i + 1;
    tmp = (P(l + 1, i - 1) - P(l, i - 1)) % kP, (tmp += kP) %= kP;
    (cnt *= tmp) %= kP;
    (ans += (cnt * P(f[n], kP - 2) % kP)) %= kP;
  }
  cout << ans << '\n';
  return 0;
}

#C. 依久依久

考虑前缀和,则 \(\texttt{ans}=S_r \bigoplus S_{l-1}\)

可以使用递归求解,令 \(k\) 为最大的 \(k\) 满足 \(fib_k \le n\)\(S_n=S_{fib_k-1}\bigoplus S_{n-fib_k} \bigoplus ([(n-fib_k) \bmod 2=0] \times fib_k)\)

还可以顺便记忆化一下,降低复杂度

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 1e7 + 5;

int t;
LL l, r, f[kMaxN];
unordered_map<LL, LL> mp;

LL S(LL x, LL ret = 0) {
  if (x <= 0) {
    return 0;
  }
  if (mp.count(x)) {
    return mp[x];
  }
  for (int i = 88; i; i--) {
    if (x >= f[i]) {
      if (x - f[i] % 2 == 0) {
        ret ^= f[i];
      }
      return mp[x] = ret ^ S(x - f[i]) ^ S(f[i] - 1);
    }
  }
  return 0;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), f[1] = 1, f[2] = 2;
  freopen("yijiu.in", "r", stdin);
  freopen("yijiu.out", "w", stdout);
  for (int i = 3; i <= 88; i++) {
    f[i] = f[i - 1] + f[i - 2];
  }
  for (cin >> t; t; t--) {
    cin >> l >> r, cout << (S(r) ^ S(l - 1)) << '\n';
  }
  return 0;
}

#D. 补幺梨

比较板子的同余最短路,模数为 \(min\{a_i,m\}\),答案为 \(min\{dis_i-k\}\)

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 1e7 + 5, kMaxM = 3e7 + 5;

int t, n, m, a[kMaxN];
LL dis[kMaxM], ans = -1;
priority_queue<pair<LL, LL>, vector<pair<LL, LL>>, greater<pair<LL, LL>>> q;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  freopen("pear.in", "r", stdin);
  freopen("pear.out", "w", stdout);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    cin >> a[i], m = min(m, a[i]);
  }
  fill(dis, dis + m, 1e18);
  for (q.push({0, 0}), dis[0] = 0; !q.empty();) {
    auto [w, v] = q.top();
    q.pop();
    if (dis[v] != w) {
      continue;
    }
    for (int i = 1; i <= n; i++) {
      if (dis[(v + a[i]) % m] > dis[v] + a[i]) {
        dis[(v + a[i]) % m] = dis[v] + a[i], q.push({dis[(v + a[i]) % m], (v + a[i]) % m});
      }
    }
  }
  for (int i = 0; i < m; i++) {
    ans = max(ans, dis[i] - m);
  }
  cout << ans << '\n';
  return 0;
}
posted @ 2024-09-24 15:45  BluemoonQwQ  阅读(19)  评论(0编辑  收藏  举报