欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > 【codeforces 2104D,E】欧拉筛,字符串上dp

【codeforces 2104D,E】欧拉筛,字符串上dp

2025/4/30 11:17:19 来源:https://blog.csdn.net/Doctor_Anonymous/article/details/147620652  浏览:    关键词:【codeforces 2104D,E】欧拉筛,字符串上dp

【codeforces 2104D,E】欧拉筛,字符串上dp

Problem - D - Codeforces

题意:

给定一个长度为 n n n的数组 a 1 , a 2 , . . . , a n a_1, a_2, ... , a_n a1,a2,...,an,其中 2 ≤ a i ≤ 1 0 9 2 \leq a_i \leq 10^9 2ai109 1 ≤ n ≤ 4 × 1 0 5 1 \leq n \leq 4 \times 10^5 1n4×105

我们可以进行以下的操作任意次(或者不进行)

  • 花费一块钱,可以选择数组中任意一个元素,将其增加 1 1 1
  • 得到一块钱,并任选数组中的元素并将其减少 1 1 1

定义理想数组为:

  • 每个元素都大于等于 2 2 2
  • 数组中元素任选两个元素都互质。若数组的长度小于 2 2 2,该条件自动满足

初始的数组 a a a可能是理想的,也可能不是。数组 a a a可以通过上述操作变成理想数组,也有可能变不成。现在我们可以删除一些元素,使得无法变成的数组可以变成。问最少的删除次数是多少?(若为 0 0 0,表明初始的数组 a a a已经是理想数组或可以通过上述两种操作变成理想数组)


思路:

性质 1 1 1:首先分析两种操作,发现通过这两种操作,我们可以将数组 a a a变成相同长度的,所有元素和比当前数组小的任意数组。

证明:若将一个数字减少 x x x,那么另一个数字最多可以增加 x x x。当然,另一个数字增加的数量完全可以小于 x x x。当然,另一个数字完全可以选择减少。所以我们可以构造出任意所有元素和比之前小的数组。

注意到,若想使得所有元素两两互质,那么所有数必须是质数。

我们先筛出 4 × 1 0 5 4 \times 10^5 4×105个质数,计算前缀和,记为 p r e P r i m e s [ i ] prePrimes[i] prePrimes[i]

将数组元素从大到小排序,计算前缀和,记为 p r e N u m [ i ] preNum[i] preNum[i]

若条件 p r e N u m [ i ] ≥ p r e P r i m e s [ i ] ( 1 ≤ i ≤ n ) preNum[i] \geq prePrimes[i](1 \leq i \leq n) preNum[i]prePrimes[i](1in)满足,则一定可以通过性质 1 1 1得到理想数组。此时删除的元素数量是 n − i n - i ni

为什么数组从大到小排序,每次删除最小的元素?质数从小到大计算前缀和?因为这样更容易满足 p r e N u m [ i ] > p r e P r i m e s [ i ] preNum[i] > prePrimes[i] preNum[i]>prePrimes[i]


代码如下:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"#define int LLconst int N = 4e5 + 10, M = 6e6 + 10;
int n, a[N], s[N];
bool st[M];
vector<int> primes, sp;void init(int n) {for (int i = 2; i <= n; i ++) {if (st[i] == false) primes.push_back(i);for (int j = 0; j < primes.size() && primes[j] <= n / i; j ++) {st[i * primes[j]] = true;if (i % primes[j] == 0) break;}}int cnt = primes.size();primes.insert(primes.begin(), 0);sp.push_back(0);int sum = 0;for (int i = 1; i <= cnt; i ++) {sum += primes[i];sp.push_back(sum);}
}void solve() {cin >> n;for (int i = 1; i <= n; i ++) cin >> a[i];sort(a + 1, a + n + 1, greater<int>());memset(s, 0, sizeof s);for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i];int res = 1e9;for (int i = n; i >= 1; i --) {if (s[i] >= sp[i]) {res = min(res, n - i);break;}}cout << res << endl;
}signed main() {ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);init(6000000);int t; cin >> t;while (t --) solve();return 0;
}

Problem - E - Codeforces

题意:

给定一个字符串 s s s,其长度为 n n n。给出 q q q个查询,每个查询给出一个字符串 t t t,问再往字符串 t t t后加几个字符可以使得 t t t不是 s s s的子序列。(其中 s s s t t t只能由小写字母的前 k k k个字母组成)。


思路:

我们希望知道两件事情:

  1. 快速知道字符串 t t t s s s的前几个字符的子序列
  2. s s s的第 i i i个字符开始,还需要加几个字符,可以使 i i i跳到 n + 1 n + 1 n+1

初始化 n x t [ i ] [ j ] nxt[i][j] nxt[i][j]数组,表示第 i i i个位置往后看, A S C I I ASCII ASCII码为 j + 97 j + 97 j+97的字符出现的第一次出现的位置。初始化时倒着初始化很方便。 l s t [ i ] lst[i] lst[i]表示 A S C I I ASCII ASCII码为 i + 97 i + 97 i+97的字符上一次出现的位置

d p [ i ] dp[i] dp[i]表示前 i i i个字符已经完成了匹配,还需加几个字符使得字符串不是 s s s的子序列。 d p dp dp数组倒着转移。

对于给定的询问,我们先将指针 i i i跳到位置 i d x idx idx,那么 d p [ i d x ] dp[idx] dp[idx]就是答案

为什么这样定义状态?考虑指针 i i i跳的过程。遇见不同的字符串 t t t时, i i i是变量


代码如下:

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define endl "\n"const int N = 1e6 + 10, M = 30;
int n, k, q;
char a[N];
int nxt[N][M], lst[M], dp[N];int main() {ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);cin >> n >> k;for (int i = 1; i <= n; i ++) cin >> a[i];for (int i = 0; i < k; i ++) {lst[i] = n + 1;nxt[n + 1][i] = n + 1;}	memset(dp, 0x3f, sizeof dp);dp[n + 1] = 0;for (int i = n; i >= 0; i --) {for (int j = 0; j < k; j ++) {nxt[i][j] = lst[j];dp[i] = min(dp[i], dp[nxt[i][j]] + 1);}	if (i != 0) lst[a[i] - 'a'] = i;}cin >> q;while (q --) {string str;cin >> str;int idx = 0;for (int i = 0; i < str.size(); i ++) {idx = nxt[idx][str[i] - 'a'];}cout << dp[idx] << endl;}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词