月度归档: 2019 年 8 月

[CF7D]Palindrome Degree 题解

[CF7D]Palindrome Degree 题解

题目地址:Codeforces:Problem – 7D – Codeforces、洛谷:CF7D Palindrome Degree – 洛谷 | 计算机科学教育新生态

题目描述

String s of length n is called k-palindrome, if it is a palindrome itself, and its prefix and suffix of length $\lfloor n/2 \rfloor$ are (k - 1)-palindromes. By definition, any string (even empty) is 0-palindrome.

Let’s call the palindrome degree of string s such a maximum number k, for which s is k-palindrome. For example, “abaaba” has degree equals to 3.

You are given a string. Your task is to find the sum of the palindrome degrees of all its prefixes.

题意简述

定义长度为$n$的字符串$s$为一个$k$阶回文串,当且仅当它本身是一个回文串,且它的长度为$\lfloor n/2 \rfloor$的前缀和后缀(即前半部分和后半部分)都是$(k-1)$阶的回文串。根据定义,任何一个字符串(包括空串)都至少是一个$0$阶回文串。

给定一个字符串,求它所有前缀的回文串阶数之和。

输入输出格式

输入格式:
The first line of the input data contains a non-empty string, consisting of Latin letters and digits. The length of the string does not exceed 5·106. The string is case-sensitive.

输出格式:
Output the only number — the sum of the polindrome degrees of all the string’s prefixes.

输入输出样例

输入样例#1:

a2A

输出样例#1:

1

输入样例#2:

abacaba

输出样例#2:

6

题解

题目已经说明了这个题的基本思路,即判断当前前缀是否是一个回文串,若是一个回文串则完成转移$f(i)=f(i/2)+1$,其中$f(i)$是前缀$s_{1 \dots i}$的回文串阶数,且$f(1)=1$。

判断是否相等可以通过字符串Hash来实现,这里不再赘述字符串Hash的原理。

复杂度$O(n)$。

代码

// Code by KSkun, 2019/8
#include <cstdio>
#include <cstring>

#include <algorithm>

typedef long long LL;

const int MAXN = 5000005;
const int BASE = 233, MO = 998244353;

int n, f[MAXN];
LL h1[MAXN], h2[MAXN], bpow[MAXN];
char s1[MAXN], s2[MAXN];

inline LL fpow(LL n, LL k) {
	n %= MO; LL res = 1;
	for(; k; k >>= 1, n = n * n % MO) {
		if(k & 1) res = res * n % MO;
	}
	return res;
}

inline LL hash(LL hsh[], int l, int r) {
	return (hsh[r] - hsh[l - 1] * bpow[r - l + 1] % MO + MO) % MO;
}

int main() {
	scanf("%s", s1 + 1);
	n = strlen(s1 + 1);
	for(int i = 1; i <= n; i++) s2[n - i + 1] = s1[i];
	bpow[0] = 1;
	for(int i = 1; i <= n; i++) bpow[i] = bpow[i - 1] * BASE % MO;
	for(int i = 1; i <= n; i++) h1[i] = (h1[i - 1] * BASE % MO + s1[i]) % MO;
	for(int i = 1; i <= n; i++) h2[i] = (h2[i - 1] * BASE % MO + s2[i]) % MO;
	f[1] = 1; int sum = 1;
	for(int i = 2; i <= n; i++) {
		if(hash(h1, 1, i / 2) == hash(h2, n - i + 1, n - i + i / 2)) f[i] = f[i / 2] + 1;
		sum += f[i];
	}
	printf("%d", sum);
	return 0;
}
[CF6A]Triangle 题解

[CF6A]Triangle 题解

题目地址:Codeforces:Problem – 6A – Codeforces、洛谷:CF6A Triangle – 洛谷 | 计算机科学教育新生态

题目描述

Johnny has a younger sister Anne, who is very clever and smart. As she came home from the kindergarten, she told his brother about the task that her kindergartener asked her to solve. The task was just to construct a triangle out of four sticks of different colours. Naturally, one of the sticks is extra. It is not allowed to break the sticks or use their partial length. Anne has perfectly solved this task, now she is asking Johnny to do the same.

The boy answered that he would cope with it without any difficulty. However, after a while he found out that different tricky things can occur. It can happen that it is impossible to construct a triangle of a positive area, but it is possible to construct a degenerate triangle. It can be so, that it is impossible to construct a degenerate triangle even. As Johnny is very lazy, he does not want to consider such a big amount of cases, he asks you to help him.

题意简述

有4根木棍,长度已知,问是否能选出3根组成一个三角形或者退化的三角形(两边之和等于第三边)。

输入输出格式

输入格式:
The first line of the input contains four space-separated positive integer numbers not exceeding 100 — lengthes of the sticks.

输出格式:
Output TRIANGLE if it is possible to construct a non-degenerate triangle. Output SEGMENT if the first case cannot take place and it is possible to construct a degenerate triangle. Output IMPOSSIBLE if it is impossible to construct any triangle. Remember that you are to use three sticks. It is not allowed to break the sticks or use their partial length.

输入输出样例

输入样例#1:

4 2 1 3

输出样例#1:

TRIANGLE

输入样例#2:

7 2 2 4

输出样例#2:

SEGMENT

输入样例#3:

3 5 9 1

输出样例#3:

IMPOSSIBLE

题解

参考资料:题解 CF6A 【Triangle】 – Heartlessly 的博客 – 洛谷博客

这个题目作为A题自然是不难的,写这篇题解主要是为了记录下这个A题简化的有趣思想。

首先,我们对4根木棍按长度排序,有序序列具有很好的性质。考虑从中选出3根木棍的所有选择情况:
1 2 3 | 1 3 4 | 2 3 4 | 1 2 4
如果选出的木棍能组成三角形,1+2>4的时候同时满足1+2>3,因此1 2 4包含在1 2 3的情况中;同理1 3 4包含在2 3 4中。组成退化的三角形同理。

经过上面的分析,我们只需要考虑1 2 3和2 3 4两种情况即可。

这种合并同类选项、减少情况数量的方法在其他题目中也有应用,可以有效减少代码细节,是很有意思的做法。

代码

// Code by KSkun, 2019/8
#include <cstdio>
#include <cctype>

#include <algorithm>

typedef long long LL;

inline char fgc() {
	static char buf[100000], * p1 = buf, * p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
		? EOF : *p1++;
}

inline LL readint() {
	LL res = 0, neg = 1; char c = fgc();
	for(; !isdigit(c); c = fgc()) if(c == '-') neg = -1;
	for(; isdigit(c); c = fgc()) res = res * 10 + c - '0';
	return res * neg;
}

inline char readsingle() {
	char c;
	while(!isgraph(c = fgc())) {}
	return c;
}

const int MAXN = 5;

int a[5];

int main() {
	for(int i = 1; i <= 4; i++) {
		a[i] = readint();
	}
	std::sort(a + 1, a + 5);
	if(a[1] + a[2] > a[3] || a[2] + a[3] > a[4]) puts("TRIANGLE");
	else if(a[1] + a[2] == a[3] || a[2] + a[3] == a[4]) puts("SEGMENT");
	else puts("IMPOSSIBLE");
	return 0;
}