AtCoder Beginner Contest 249 赛时记录
赛时只切了 4 题,2022 开年来的第一次,输麻了/ll
掉大分
安慰一下自己,常在河边走,哪有不掉分~
A - Jogging
直接按照题目要求的模拟一下,看看谁的得分高就可以。
tnnd 题面一开始错了,WA 了一发,比着题面和样例看了半天才看出来/px
B - Perfect String
随便拿个桶记录下就好了。
C - Just K
很小,直接 枚举,然后 求一下价值,对价值取个 就好了。
signed main() {
int n = read(), K = read();
for(int i = 1; i <= n; ++i) {
cin >> s + 1;
int len = strlen(s + 1);
for(int j = 1; j <= len; ++j) {
cnt[i][s[j] - 'a'] ++;
}
}
int Max = 0;
for(int S = 0; S < (1 << n); ++S) {
int ans = 0;
for(int i = 0; i < 26; ++i) {
int res = 0;
for(int j = 1; j <= n; ++j) {
if(!((S >> j - 1) & 1)) continue;
res += cnt[j][i];
}
if(res == K) ans ++;
}
// cout << S << " " << ans << "\n";
Max = max(Max, ans);
}
cout << Max << "\n";
return 0;
}
D - Index Trio
发现 ,果断把 扔到值域上统计出现次数。
然后暴力枚举一下 和 就好了,复杂度是喜闻乐见的调和级数 。
注意我们并不需要考虑去重的问题。
signed main() {
n = read();
for(int i = 1; i <= n; ++i) cnt[read()] ++;
int M = 200000;
for(int i = 1; i <= M; ++i)
for(int j = i; j <= M; j += i)
ans += cnt[i] * cnt[j] * cnt[j / i];
cout << ans << "\n";
return 0;
}
E - RLE
重新看了一下 E 题,随便冲了一发就过了。
设 表示填完前 个位置,缩减后长度为 的方案数。
显然有一个 的转移就是:
其中 表示一个长度为 的字符串缩减后的长度。这个可以预处理一下。
因为 的值只有四种取值(),而转移的时候这些又是连续的。
我们考虑处理一个前缀和 。
那么转移后面的求和部分可以利用这个前缀和快速算出。
我们只需要暴力写一下四种取值的转移即可。
总复杂度是 的。
下面是代码,代码去掉了不重要的部分。
#define int long long
const int MAXN = 3e3 + 100;
const int INF = 1e9 + 7;
int n, mod, ans = 0;
int f[MAXN][MAXN]; // f[i][j] 表示前 i 个位置,长度为 j 的方案数
int sum[MAXN][MAXN]; // sum[i][j] = \sum_{k=1}^{i} f[k][j]
int len[MAXN];
int Mod(int x) {
if(x < 0) return (x % mod + mod) % mod;
return x % mod;
}
int Get(int i, int j, int L, int R) {
if(j - len[L] < 0) return 0;
return Mod(sum[max(0ll, i - L)][j - len[L]] - sum[max(0ll, i - R)][j - len[L]]) * 25 % mod;
}
signed main() {
n = read(), mod = read();
for(int i = 1; i < 10; ++i) len[i] = 2;
for(int i = 10; i < 100; ++i) len[i] = 3;
for(int i = 100; i < 1000; ++i) len[i] = 4;
for(int i = 1000; i <= 3000; ++i) len[i] = 5;
f[0][0] = 1;
for(int i = 1; i <= n; ++i) {
f[i][len[i]] = 26;
for(int j = 1; j <= n; ++j) {
f[i][j] = Mod(f[i][j] + Get(i, j, 1, 10));
f[i][j] = Mod(f[i][j] + Get(i, j, 10, 100));
f[i][j] = Mod(f[i][j] + Get(i, j, 100, 1000));
f[i][j] = Mod(f[i][j] + Get(i, j, 1000, 3001));
sum[i][j] = Mod(sum[i - 1][j] + f[i][j]);
}
}
for(int j = 1; j < n; ++j) ans = Mod(ans + f[n][j]);
cout << ans << "\n";
return 0;
}
F - Ignore Operations
因为还没调出来,先口胡一下做法。 调出来了,思路没有问题。
就是倒着枚举,遇到 的时候,看一下从这里到最后获得的价值最大是多少,对答案去一个 。过去之后要用一次跳来消除这个位置的影响。
动态维护一个 ,每遇到一个 ,如果 ,那么可以不用跳。否则的话,把它扔进一个堆里,如果堆里的元素个数 ,取出最小的加进 中。
中途如果扫过 后 ,那么可以直接 break
掉。
最后直接输出答案即可。
#define int long long
const int MAXN = 4e5 + 10;
const int INF = 1e18 + 7;
const int mod = 998244353;
int n, K, ans = - INF, sum = 0;
int a[MAXN], b[MAXN];
priority_queue<int, vector<int>, less<int> > Q;
signed main() {
n = read(), K = read();
for(int i = 1; i <= n; ++i) a[i] = read(), b[i] = read();
ans = 0; int Cnt = 0;
for(int i = 1; i <= n; ++i) {
if(a[i] == 1) ans = b[i];
else ans += b[i], ++Cnt;
}
a[0] = 1, b[0] = 0;
for(int i = n; i >= 0; --i) {
if(a[i] == 1) {
ans = max(ans, b[i] + sum);
--K;
if(K < 0) break;
} else {
if(b[i] >= 0) sum += b[i];
else Q.push(b[i]);
}
while(!Q.empty() && Q.size() > K) {
sum += Q.top(), Q.pop();
}
}
cout << ans << "\n";
return 0;
}
分类:
VP记录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话