20251115NOIP模拟

总结

预计:120,实际:120

A

预计:60,实际:60

  • 考试思路历程:先是想到了按大小排序,每次都把最小的乘以k,但是由于需要取模且时间复杂度为O(m*log(n)),所以这个暴力只能拿到少部分分。后来考虑使用DP,0个办法。也对$log_k^a[i]$方面思考过了,但是不知道怎么做后继
  • 题解:也是对$log_k^a[i]$考虑,说是直接用堆维护一下把所有的对数补齐然后O(log)直接加,但是我没有明白为什么在前面的补齐过程可以不取模不炸longlong

更正如下:

点击查看代码
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

const ll kMod = 1e9 + 7;
const int kN = 2e5 + 5;

ll qpow (ll a, ll b) {
  ll sum = 1;
  for (ll i = 1; i <= b; i <<= 1, a = a * a % kMod) {
    if (b & i) sum = sum * a % kMod;
  }
  return sum;
}

ll sum = 0;
priority_queue <ll, vector <ll>, less <ll> > q;
ll a[kN], k, maxi;
int n, m;

int main () {
  cin.tie (0)->sync_with_stdio (0);

  cin >> n >> m >> k;
  bool flag = 0;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i];
    flag |= a[i] == 0;
    maxi = max (maxi, a[i]);
    sum = (sum + a[i]) % kMod;
  }
  if (flag) {
    cout << sum;
    return 0;
  } else if (k == 1) {
    cout << sum;
  } else {
    for (int i = 1; i <= n; ++i) q.push (-a[i]);
    // cout << q.top () << '\n';

    for (; (-q.top () * k < maxi || m % n != 0) && m > 0; --m) {
      ll tmp = q.top ();
      q.pop ();
      maxi = max (maxi, tmp * k);
      q.push (tmp * k); 
      sum = (sum + (k - 1) * (-tmp)) % kMod;
    }
    sum = sum * qpow (k, m / n) % kMod;

    cout << sum;
  }
  return 0;
}

B

预计:60,实际:60

  • 考试思路历程:想着可以先向左再向右折,先向右再向左,和不折。然后三方做法出炉,但是当我考虑如何DP时,想到0个做法
  • 题解:没有解释,但是我看了fzx的代码,发现他的DP非常巧妙,把折叠的情况和不折叠的融合在一起再分成两边(即向左再向右和向左不折叠,。。。。)

更正代码如下:

点击查看代码
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

const int kN = 8005;

ll sum[kN], dp[2][kN], rec[kN], a[kN];
int n;

int main() {
  cin.tie (0)->sync_with_stdio (0);

  cin >> n;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i];
    sum[i] = sum[i - 1] + a[i];
  }
  for (int i = 1; i <= n * 2; ++i) {
    for (int j = n; j >= 1; --j) {
      dp[0][j] = max (sum[min (n, j + i)] - sum[j - 1], dp[0][j - 1]);
    }
    for (int j = 1; j <= n; ++j) {
      dp[1][j] = max (sum[j] - sum[max (0, j - i - 1)], dp[1][j + 1]);
    }
    for (int j = 1; j <= n; ++j) {
      rec[j] ^= i * max (dp[0][j], dp[1][j]);
    }
  }

  ll ans = 0;
  for (int i = 1; i <= n; ++i) {
    ans ^= i + rec[i];
  }
  cout << ans;
  return 0;
}

C

预计:0,实际:0

  • 考试思路历程:无
  • 题解:正在观摩中

D

预计:0,实际:0

  • 考试思路历程:无
  • 题解:写代码中
posted @ 2025-11-17 13:17  姜树  阅读(13)  评论(0)    收藏  举报