Educational Codeforces Round 144 (Rated for Div. 2) A-D题解

首先,由于本人水平不够只会写四道,因此只有A-D的题解
(而且这F题怕不是为了防AK,红黑名大佬都没做,我都不敢多看一眼,再看一眼就。。。)

A. Typical Interview Problem

签到题,很显然每15个数就是一个循环,那么列举出来进行一个对比就ok了。
代码很简单就不放了。

B. Asterisk-Minor Template

找模板,大概分为三种情况
第一种,两个字符串的第一个字符或者最后一个字符相同,那么很显然答案就是在该字符前面(或者后面)加一个 * 就是一个答案。
第二种,两个字符串首尾都不相同,那么如果能在字符串中找到两个连续的字符都相同,就可以输出 * XX * 式的答案。
第三种,如果以上的情况都没有,那么说明无法找到一个这样的模板,那么直接输出NO
当时代码敲得太丑了就不放了/kk。

C. Maximum Set

本来看到这个模数吓一跳,结果好像并没有用。
题目要求求两个数,第一个数很显然,把 r / l r/l r/l后求log就行。
主要是求第二个数,
对于 l l l 来说,一直乘以2显然是一种最多的情况,那么能否乘以3呢?
假设输出的第一个数为 x x x
我们发现当 l / r ⩾ 3 × 2 x l / r \geqslant 3 \times 2^x l/r3×2x 时,是可以把其中一个位置的 X2 换成 X3 的
并且只能换一个,因为 3 2 > 2 3 3^2 > 2^3 32>23 如果换了两个,那么最后数组的大小绝对会比最大值要小。
X4 同理
所以接下来只需要找到 l 到 m i n ( 2 × l , r ) l 到 min(2 \times l, r) lmin(2×l,r)中有多少个是可以X3的,就可以得到ans了
对于每一个数据,复杂度大概就是一个O(log r) ,总复杂度就是O(t log r),检查一下发现刚好能过。
(由于本人代码能力太差了,没有过,因此贴上MXing大佬的python代码)

import math
for _ in range(int(input())):
    l, r = map(int, input().split())
    width = r - l + 1
    k = l
    n = 1
    while k <= r:
        k *= 2
        n += 1
    n -= 1
    s = math.floor(r / (2 ** (n-1)))-l+1
    kkk = math.floor((r/3) / (2**(n-2)))-l+1
    if kkk > 0:
        s += (n-1)*kkk%998244353
    print(n,int(s))

D. Maximum Subarray

不会线段树的蒟蒻只能dp。
大致是用dp(i, j)表示当前(到了第i个数,前面一共有j个数加上了x) 的最大值。
转移式 dp(i, j) = max{dp(i - 1, j - 1) + ai + x, dp(i - 1, j) + ai - x, 0}。
要注意,可以跳过所有 i < j 的情况
最后是两层(从0开始的)for查询最大值,但是只有 i + k − j < = n i + k - j <= n i+kj<=n 的值是符合条件的。
关于本人因为没有从零开始wa了无数发这件事

贴个蒟蒻的代码

#include<bits/stdc++.h>
#define int long long 

using namespace std;

const int maxn = 200010;
int T, n, k, x, ans;
int a[maxn], dp[maxn][21];

int read(){
    int x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
    return x*w;
}

signed main() {
	T = read();
	while(T --) {
		ans = 0;
		n = read(); k = read(); x = read();
		for(int i = 1; i <= n; i ++) a[i] = read();
		dp[0][0] = 0;
		for(int i = 1; i <= n; i ++) {
			dp[i][0] = max(dp[i - 1][0] + a[i] - x, (long long)0);
		}
		for(int i = 1; i <= n; i ++) {
			for(int j = 1; j <= k; j ++) {
				if(j > i) break;
				if(i - 1 >= j) dp[i][j] = max(dp[i - 1][j - 1] + a[i] + x, dp[i - 1][j] + a[i] - x);
				else dp[i][j] = dp[i - 1][j - 1] + a[i] + x;
				if(dp[i][j] < 0) dp[i][j] = 0;
//				if(i + k - j <= n) ans = max(ans, dp[i][j]);
			}
		}
		for(int j = 0; j <= k; j ++)
		for(int i = 0; i <= n; i ++) {
			if(i >= j && i + k - j <= n) ans = max(ans, dp[i][j]);
		}
		printf("%lld\n", ans);
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值