C语言程序设计杂谈(一):星期计算问题
问题描述 在星期计算问题中,我们将问题按照实现难度/复杂程度划分成若干等级: 已知2019 …
May all the beauty be blessed.
卓越班选拔考试(俗称启明考试)一般在军训一周后的一个周六进行,在这之前有一周的时间(或者一暑假的时间?)做一些准备工作。很遗憾我这段时间是玩过来的并没有做什么准备,自然也没什么可以分享的经验。
根据室友的情报,韵苑的打印店会有历年试题售卖,可以去做一下感受难度。此外需要去买一个能接收校园频段(<87MHz,FM)的收音机,在超市和韵酒的数码小店都能买到,用于收听以后各种英语考试的听力部分,建议提前买好并自行调试一下,避免考试的时候慌乱导致发挥不好。
启明考试的两个科目数学和综合的题都不算很高考,而且不太有规律可循,因此没有太好的定向准备方法,随缘考吧。
这两个考试分别在军训一周后的一个周六的上午和下午,这意味着这个周六的一天假直接被考试填了,所以可以考虑下不报启明空出一上午时间去玩(雾)。
今年好像全校的人都跑到东九去考,人巨多。
数学还算有思路,就是做出了一股数竞的味道,不过我没参加过数竞也不知道我的味觉准确不准确。写了70多分的题目,具体没底。综合第一篇人物传记按照高考的方式写呗,中美贸易战相关问题陈述事实、表明立场即可,交卷的时候也只写满了正面,反面一笔都没动。
英语在下午,由于老师反复强调把作文答题纸撕下来,我就只看见了作文纸上的一个标题,以为命题作文,就随便发挥了下。交完答题纸之后才发现作文要求在试卷的第一页,直接爆炸。听力不太适应,阅读文章巨长,其他的体验还好。
总的感觉就是,除了不太会做之外问题不大。本来以为自己要凉了。
糊里糊涂考完试之后又浪了几天,没想到在名单里看到了我的名字,吓了一大跳。面试要求准备自传、个人简历、相关证书复印件,在收到名单之后还有3个晚上给我准备所有的材料。
自传本来是打算糊弄一下的,想着要是带去面试了好像不太好,于是整个推翻重构,花了2晚上时间。个人简历去找了个模板,在中秋节班级活动结束之后一通改,在ddl前肝出来了。复印件本来就有存档,直接拿去打印出来就行。这是面试的前一晚,简历肝到1点多,收拾了一下材料就睡了。
前一天还想着早上去买一罐白MONSTER喝提提神,结果发现售货机里只有黑罐,于是作罢去买咖啡喝。用月饼凑合了一顿早饭就跑去面试了,结果发现校车排长队,于是骑了个单车跑去,被绝望坡整成绝望还被校车反超,体验极差。
正门没开,于是绕到侧门上楼,找了半天房间,坐在一个物理实验室里等候。信卓面试奇快无比,没一会就轮到我了,在进去之前还有点紧张,翻看我自招时准备的自我介绍和简历,整理自我介绍的思路。学长说面试就是一个老师了解你的过程,不用太紧张,于是我就当真了放松了一些。
进去之后被要求做一个2min的英文自我介绍,直接懵逼,然后按照中文介绍的思路慢慢说下去,尽量大略地描述了自己学习生活中比较大的事情和比较重要的经历。自我介绍中关于开发和竞赛经历的部分应该是吸引到了面试老师,之后的一系列问题基本都围绕着开发和竞赛两块进行,还提到了为什么要从光电换到电信以及能否吃苦之类的问题。期间老师没有太为难或者给出负面评价,相反还偶尔正面评价,让我松了一口气。
注:卓越班面试可能在不同年级、不同班级之间存在较大差异,经验仅供参考。本人参加的是电信卓越班选拔。
后来才察觉到我的文字材料白准备了,因为整个过程中都是我和老师吹水,老师并不对我的文字材料感兴趣,一眼都没看。
面试完就跑路回韵苑瘫着,然后又跑去中操体测,跑完1km之后难受了好久……偏题了。
在转专业群里聊起来面试的时候看到很多同学说面试老师会故意为难他们和提出刁钻的问题,以检测抗打击的能力,这和我所经历的面试区别有点大,这大概是为什么老师最后问了我能否吃苦这个问题的原因吧。而且大概是因为自我介绍能把老师吸引住,问的问题也基本围绕自我介绍里的内容,这也是一点区别。总之我这一趟还是挺特殊的,可能没有太大的参考价值。
之后就有点飘了,因为面试给我的感觉很不错。16号、17号等了两天名单,最后等出了个教务处的总表,看到了我的名字,意料之中但是很开心。
虽然我大概是很浪的那种人,以后也得多努努力,todolist还有Python、Web安全、日语三个大内容,慢慢来吧。
经验之谈的话,首先笔试分好看点是硬道理;面试的时候老师可能会看重以往课余做的独特经历,例如对于信卓来说项目开发、电子DIY之类相关的经历可能会成为你的加分项;自我介绍可能会遇到英语表达,慢慢来吧,我口语也很菜;自我介绍足够有亮点的话可能会把面试老师往你擅长的问题上引导;面试可能会遇到故意为难的情况,冷静对待;在专业人士面前说谎很容易被拆穿,表达尽量真实,可以减少一些麻烦。
另外对于笔试的数学和综合,据说每年题目变化比较大无法针对准备。我个人体验是数学不太高考,有点数竞的味道,不过基本都属于高中数学升华提高的一部分,并未超出太远,如果学数学的时候老师有讲扩展内容会好对付一些。综合的人物传记我是用高考语文的套路作答的,中美贸易战话题需要对时事有一定了解,总的来说比较考察表达能力和个人的想法、时事的了解程度吧。
意料之外的笔试入围、意料之中的面试通过,在这短短几天的时间里,一场校内的考试让我对自己的评价和规划有了很大的转变。
现在的我,也许能做出一点事情来呢。——产生了这样的想法。
会加油的,为了一些想做的事情,也为了自己对自己的期望和兴趣要求。感谢一直以来支持、鼓励、帮助我的各路友人,也希望大家轻点diss我这种菜鸡[快哭了emoji]。
KSkun 于2019/9/18
题目地址: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;
}
题目地址: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;
}