Codeforces Global Round 7笔记

Codeforces Global Round 7笔记

感想

耻辱场。做出三道题,但每道题平均交了4遍还多,第一题没有第一眼想出正确答案,Rating还是-60,心累。感觉还是要放平心态,求稳。并且多做思维题,思维还是过于僵化。

实时Rating:1304,不能再低了,再低真对不起我自己了。

题目

A Bad Ugly Numbers

解析

给定一个 n n n,要求一个 n n n位数 s s s,满足: s s s的每一位都不为0,且s不能被组成它的每个数字整除。 n ≤ 1 0 5 n \le 10^5 n105

说实话我没有先敲出来这个题。既然 n n n这么大一定不能套数了。赛场上用计算器摆了好几种关于和「7」有关的数,我也不知道为什么当时对7有如此的执念,明明小数点后面会循环,数长了之后总会能除开的……最后发现

77777 … 4 ‾ \overline{77777\dots4} 777774

的小数点后永远是.5,于是提交通过。提交时由于太过急躁,第一次选错了语言,后几次试了错误的答案。这题答案不唯一,标解是用了

23333 … 3 ‾ \overline{23333\dots3} 233333

代码

#include 

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

const size_t _Siz = 103020;

int T;

int main(int argc, char **argv)
{
	T = nextInt();
	while (T--)
	{
		int n = nextInt();
		if (n == 1)
		{
			std::cout << -1 << std::endl;
			continue;
		}
		for (int i = 1; i <= n - 1; i++)
			std::cout << 7;
		std::cout << 4 << std::endl;
	}
	return 0;
}

B Maximums

解析

给定一个数组 a a a,由非负整数构成,给定数组 x x x,规定 x i = m a x ( a 1 , a 2 , … , a i − 1 ) x_i = max(a_1, a_2, \dots, a_{i - 1}) xi=max(a1,a2,,ai1),给定数组 b i = a i − x i b_i = a_i - x_i bi=aixi。现已知数组 b b b,要求倒推出 a a a

纯模拟。没啥技术含量。根据题目, a i = b i + x i a_i = b_i + x_i ai=bi+xi,显然 x i x_i xi可求,就是 b 1 b_1 b1 b i − 1 b_i - 1 bi1取个max。然后加起来就完事。

这题交了好几遍,就是因为没有读好题,把题目想得过于简单。

代码

#include 

#define debug(X) std::cout << #X << " : " << X << std::endl

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

const size_t _Siz = 503020;

ll T, b[_Siz] = { 0 }, t[_Siz] = { 0 };

int main(int argc, char **argv)
{
	int n = nextInt();
	ll Mx = 0;
	bool flag = false;
	for (int i = 1; i <= n; i++)
	{
		b[i] = nextInt();
		t[i] = (t[i - 1] + b[i] > t[i - 1]) ? (t[i - 1] + b[i]) : t[i - 1];
	}
	std::cout << b[1] << ' ';
	for (int i = 2; i <= n; i++)
		std::cout << t[i - 1] + b[i] << ' ';
	std::cout << std::endl;
}

C Permutation Partitions

解析

给定一个排列 p p p,再给定一个 k k k,使得 p p p可以被分成不相交的 k k k份,定义 v a l u e value value为各份最大值的和,求 v a l u e value value的值和所有满足的 v a l u e value value的方案数。

这题交了7遍,还是没过。第一问求 v a l u e value value好办,直接前 k k k大加起来即可。第二问的话,要选定一个分界线,分界线可以放在前k大的数字后面到下一个数字前。设两个数字位置为 p o s i pos_i posi p o s i + 1 pos_{i + 1} posi+1,则方案数有 p o s i + 1 − p o s i pos_{i + 1} - pos_i posi+1posi个,然后乘起来就好。

代码

#include 

#define debug(X) std::cout << #X << " : " << X << std::endl

typedef long long ll;

const ll mod = 998244353ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

int main(int argc, char **argv)
{
	int n, k, p = -1, ans = 1, sum = 0;
	n = nextInt(), k = nextInt();
    for (int i = 1; i <= n; i++)
	{
    	int x = nextInt();
        if (x >= (n - k + 1))
		{
            sum += x;
            if (p != -1)
                ans = ans * (i - p) % mod;
            p = i;
        }
    }
	std::cout << sum << ' ' << ans << std::endl;
	return 0;
}

D Prefix-Suffix Palindrome

解析

给定一个字符串,要求它里面的回文子串,满足:该字串由两段组成,前段是原串的前缀,后段是原串的后缀。

纯模拟,蛮练手的这个题。确定下思路之后往下写就好了。Hard version没测,目测应该也能过。

代码

#include 

#define debug(X) std::cout << #X << " : " << X << std::endl

typedef long long ll;

ll nextInt()
{
	ll num = 0;
	char c = 0;
	bool flag = false;
	while ((c = std::getchar()) == ' ' || c == '\r' || c == '\t' || c == '\n');
	if (c == '-')
		flag = true;
	else
		num = c - 48;
	while (std::isdigit(c = std::getchar()))
		num = num * 10 + c - 48;
	return (flag ? -1 : 1) * num;
}

const size_t _Siz = 503020;

ll T;
		
std::string st;

bool palin(std::string stx, int l, int r)
{
	std::string st2 = stx.substr(l, r - l + 1);
	std::string st1 = st2;
	std::reverse(st1.begin(), st1.end());
	return (st1 == st2);
}


int main(int argc, char **argv)
{
	T = nextInt();
	while (T--)
	{
		std::cin >> st;
		int len = st.length();
		if (len == 1)
		{
			std::cout << st << std::endl;
			continue;
		}
		if (len == 2)
		{
			if (st[0] == st[1])
				std::cout << st << std::endl;
			else
				std::cout << st[0] << std::endl;
			continue;
		}
		std::string ans, anst;
		int head = 0, tail = len - 1;
		while (head != tail && head != tail - 1)
		{
			if (st[head] == st[tail])
				ans += st[head];
			head++;
			tail--;
		}
		if (head == 1 && tail == len - 2)
		{
			head = 0, tail = 1;
			int t1 = 0, t2 = 0;
			while (palin(st, 0, tail++)) t1++;
			head = len - 2, tail = len - 1;
			while (palin(st, head--, len - 1)) t2++;
			if (t1 >= t2)
				std::cout << st.substr(0, t1) << std::endl;
			else
				std::cout << st.substr(len - t2, len - 1) << std::endl;
			continue;
		}
		int p = head, q = tail, r = 0, s = 0;
		for (q = tail; q > p; q--)
			if (palin(st, p, q))
			{
				r = q;
				anst += st.substr(p, q - p + 1);
				break;
			}
		for (p = r + 1; p < tail; p++)
			if (palin(st, p, tail))
			{
				anst += st.substr(p, tail - p + 1);
				break;
			}
		std::string tans = ans;
		std::reverse(tans.begin(), tans.end());
		std::cout << ans + anst + tans << std::endl;
	}
}

你可能感兴趣的:(心得)