当前位置: 首页 > news >正文

Codeforces 1042G Wafu! 题解 [ 绿 ] [ 数学 ] [ 线性 DP ] [ 前缀和 ] [ 暴力枚举 ]

Wafu!:感觉是比较 naive 的题。

首先可以手模一下样例,发现好像把一个数删掉后还要把它前面的所有数再操作一遍,因此操作数是以很快的速度增长的。写了个前缀和优化 DP 可以发现把 \(x\) 以及其衍生的数完全删掉需要花费 \(2^{x-1}\),也就是说完整删除的元素就是 \(1\sim 30\)。这种操作数为 \(\log\) 级别的 trick 应该还是挺常见的。

因此我们可以先暴力枚举被完整删除的元素,先把能完整删除的元素删完。对于剩下不能完整删除的元素,我们直接模拟,先把这个元素 \(x\) 自己删掉,然后对于产生的 \(1\sim x-1\) 的元素逐个考虑,尝试将它删除。如果遇到一个删不了的,就证明后面的也删不了了,因此递归地对剩下的操作考虑,直到所有操作被执行完毕。不难发现,这一部分可以利用上文预处理出的 DP 值求出。于是总体时间复杂度就是 \(O(T\log^2V)\) 的。

关于时间复杂度的证明:首先完整删除的元素是最多删 \(\log V\) 次的;而对于无法完整删除的元素,递归的过程中显然每一轮最多删 \(\log V\) 次,且最多会递归 \(\log V\) 层(因为每一轮会使得剩余操作数至少减少到原来的一半),因此时间复杂度是 \(O(T\log^2V)\)

注意 DP 数组的值域最多只到了 \(2\times 10^5\),所以对于越界的访问必须特判,否则会 RE。

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const int N = 200005;
const ll mod = 1e9 + 7;
ll n, k, s[N], f[N], g[N], smf[N], smg[N], ans = 1;
void init()
{f[1] = g[1] = smf[1] = smg[1] = 1;for(int i = 2; i < N - 1; i++){f[i] = min(ll(1e9 + 5), smf[i - 1] + 1);g[i] = (smg[i - 1] * i) % mod;smf[i] = min(ll(1e9 + 5), smf[i - 1] + f[i]);smg[i] = (smg[i - 1] * g[i]) % mod;}
}
void work(ll x)
{if(x == 0) return;for(int i = 1; i <= 32; i++){if(x <= 0) break;if(x - f[i] >= 0){x -= f[i];ans = (ans * g[i]) % mod;}else{ans = (ans * i) % mod;x--;break;}}work(x);
}
void solve()
{cin >> n >> k;for(int i = 1; i <= n; i++) cin >> s[i];sort(s + 1, s + n + 1);ans = 1;for(int i = 1; i <= n; i++){if(k <= 0) break;if(s[i] < N && k - f[s[i]] >= 0){ans = (ans * g[s[i]]) % mod;k -= f[s[i]];}else{ans = (ans * s[i]) % mod;work(k - 1);cout << ans << '\n';return;}}cout << ans << '\n';
}
int main()
{//freopen("sample.in","r",stdin);//freopen("sample.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);init();int t;cin >> t;while(t--) solve();return 0;
}
http://www.aitangshan.cn/news/7.html

相关文章:

  • 第二章:Linux基础命令
  • 题解:P4779 【模板】单源最短路径(标准版)
  • 事倍功半是蠢蛋39 cursor 报错user is unauthorized
  • 一个不错的AI写作工具
  • 2025CSP-S模拟赛33 比赛总结