Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

铃盛密码之谜
命题人:LZZ 难度:极简

按题意模拟即可。

#include <stdio.h>
#include <string.h>
#define maxn 1005
int main(void)
{
int t;
char str[maxn];
scanf("%d",&t);
while (t--)
{
scanf("%s",str);
int len=strlen(str);
str[len-str[len-1]+'0']='\0';
puts(str);
}
return 0;
}

yjy的校验和

命题人:WaviFreka 难度:简单

本题主要考察位运算知识。对于不熟悉位运算的同学,则考察现场学习新知识的能力。

#include <stdbool.h>
#include <stdio.h>
int main(){
long long a = 0, b = 0, n, x;
scanf("%lld",&n);
while(n--){
scanf("%lld",&x);
a = (a + (x >> 16)) % ((1 << 16));
b = (b + (x % ((1 << 16)))) % ((1 << 16));
}
a ^= 0xa5a5;
b ^= 0xa5a5;
a &= b;
printf("%lld\n",a);
return 0;
}

file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 1/7
2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

埃及扑克之谜

命题人:LZZ 难度:简单

按题意,直接暴力代码计算即可。由于本题只有三种答案,另一个办法是手算后输出即可。

#include <stdio.h>
int q[300];
void run() {
int x, y;
char a, b;
scanf("%d%c%d%c", &x, &a, &y, &b);
for (int i = 0; i < 300; ++i) {
q[i] = 0;
}
q[a] = x; q[b] = y;
int ans = 0, fm = 0;
for (int i = 'a'; i <= 'j'; ++i) {
for (int j = i + 1; j <= 'j'; ++j) {
for (int o = 1; o <= 5; ++o) {
fm++;
q[i] += o;
q[j] += 6 - o;
if (q[a] && q[a] % 5 == 0 || q[b] && q[b] % 5 == 0 ||
q[i] && q[i] % 5 == 0 || q[j] && q[j] % 5 == 0)ans++;
q[i] -= o;
q[j] -= 6 - o;
}
}
}
for (int i = ans; i > 1; --i) {
if (fm % i == 0 && ans % i == 0) {
ans /= i;
fm /= i;
}
}
printf("%d/%d\n", ans, fm);
}
int main() {
int t;
scanf("%d", &t);
while (t--) run();
return 0;
}
/*
Input:
3
1e 5c
2e 4c
3e 3c
Output:
22/25
82/225

file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 2/7
2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

2/5
*/

间隔就座

命题人:Pecco 难度:较难

设n个连续座位的期望最终人数为f (n)。

现在假设有n个连续座位,一个新来的人如果选择第1或第n个座位,则期望最终人数为f (n − 2) + 1;
否则,如果选择第i个座位,则期望最终人数为f (i − 2) + f (n − 1 − i) + 1。所以,f (n) =
2×∑n−3
i=0 ​f (i)+2f (n−2)+n ​。
n

注意在计算中可以维护前n项f (x)的和。总时间复杂度O(n)。

#include <stdio.h>
#define MAXN 2000005
double dp[MAXN], s[MAXN];
int main() {
dp[1] = dp[2] = 1;
s[1] = 1, s[2] = 2;
for (int i = 3; i < MAXN; ++i) {
dp[i] = (s[i - 3] * 2 + dp[i - 2] * 2 + i) / i;
s[i] = s[i - 1] + dp[i];
}
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
printf("%.12f\n", dp[n]);
}
return 0;
}

叠词词,恶心心2

命题人:Pecco 难度:较难

显然,我们只需要考虑长度为4的叠词子序列。分为两种情况:

1. aaaa型:直接判断原字符串中是否有字符出现4次或以上即可(注意,设字符集大小为Σ,如果字
符串的长度超过3Σ,则一定存在字符出现4次或以上)
2. abab型:记录每个位置左边有哪些字符,右边有哪些字符。如果某个位置的字符是b,且它左右都
存在某个字符a,就记B[b][a]为1。如果发现B[a][b]和B[b][a]均为1,说明存在子序列abab或
baba。

(时间复杂度:O(nΣ),n为T 组数据的字符串长度之和,Σ为字符串集大小)

#include <stdio.h>
#i l d < t i h>
file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 3/7
2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解
#include <string.h>
#define MAXN 1000005
char s[MAXN];

int max(int x, int y) {


return x > y ? x : y;
}
void memrev(char *data, int n) {
for (char *p = data, *q = data + n - 1; p < q; ++p, --q) {
char t = *p;
*p = *q;
*q = t;
}
}
void get_z(char s[], int n, int z[]) {
memset(z, 0, sizeof(int) * n);
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (z[i - l] < r - i + 1) {
z[i] = z[i - l];
} else {
z[i] = max(r - i + 1, 0);
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
z[i]++;
l = i, r = i + z[i] - 1;
}
}
}
int solve(char s[], int n) {
static char s1[MAXN], s2[MAXN], s3[MAXN], s4[MAXN];
static int z1[MAXN], z2[MAXN], z3[MAXN], z4[MAXN];
if (n <= 1) return 0;
if (n == 2) return s[0] == s[1];
int mid = n / 2;
char *u = s, *v = s + mid;
int ulen = mid, vlen = n - mid, len = ulen + vlen + 1;
memcpy(s1, v, vlen), s1[vlen] = ' ', memcpy(s1 + vlen + 1, u, ulen);
memcpy(s2, u, ulen), memrev(s2, ulen);
memcpy(s3, s1, len), memrev(s3, len);
memcpy(s4, v, vlen);
get_z(s1, len, z1), get_z(s2, ulen, z2), get_z(s3, len, z3), get_z(s4, vlen, z4
for (int i = mid - 1; i >= 0; --i)
if (s[i] == s[mid] && z1[vlen + 1 + i] + (i ? z2[ulen - i] : 0) >= ulen - i
return 1;
for (int i = mid; i < n; ++i)
if (s[i] == s[mid - 1] && z3[n + ulen - i] + (i < n - 1 ? z4[i + 1 - ulen]
return 1;
return solve(u, ulen) || solve(v, vlen);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%s", s);
int n = strlen(s);
puts(solve(s, n) ? "YES" : "NO");
}
file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 4/7
2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

return 0;
}

纳尔维克海战
命题人:ATt3Z1 难度:较难

题目背景:“这样,我们可以对圆锥曲线下一个统一定义:平面上到一个定点F的距离和它到一条定直线l的
距离之比是一个常数e的点的轨迹是圆锥曲线,其中F是它的焦点,直线l是它的准线,比值e是它的离心
率。”

——《人教版高中数学选修2-1》76页

本题改编自恩师龚梅勇于2020年福建省理科数学省质检所出的填空压轴题。谨以此题怀念母校与恩师。

本题需要一定的空间想象能力与计算能力。

本题题面较长,此外并无明显难点。

由题意可知作战范围的分界线方程为圆锥曲线,只需要根据题目所给数据求出分界线方程(其实是圆锥曲
线),然后由祖暅原理与梯形分割暴力求体积即可。暴力:利用for循环模拟积分,将面积近似为多个小梯
形相加,这是最朴素的积分办法。

#include <stdio.h>
#include <math.h>
typedef double db;
const db PI = 3.1415926535897932384626;
db a, b2, c, p; // 圆锥曲线参数
const int stepnum = 1e5; // 积分精度
db d, l, k, len, l1, l2;
int Ftype; // 曲线的类别
int failed;
file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 5/7
2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

double F(double x) {
if (Ftype == 1) {
double l = a * a / c - a * sqrt(1 - x * x / b2);
return l * l * PI;
}
else if (Ftype == 2) {
double l = x * x / (2 * p) + p / 2;
return l * l * PI;
}
else if (Ftype == 3) {
double l = a * sqrt(1 + x * x / b2) - a * a / c;
return l * l * PI;
}return 0;
}
double calculate() { // 十分朴素的求积分办法
double ans = 0;
for (double i = 0, steplength = l1 / stepnum; i < l1; i += steplength) {
ans += (F(i) + F(i + steplength)) * steplength / 2;
}
for (double i = 0, steplength = l2 / stepnum; i < l2; i += steplength) {
ans += (F(i) + F(i + steplength)) * steplength / 2;
}
return ans;
}

void solve1() { // 椭圆
Ftype = 1;
a = k * d / (1 - k * k), c = k * a, b2 = a * a - c * c;
if (l1 > sqrt(b2) || l2 > sqrt(b2)) failed = 1;
}
void solve2() { // 抛物线
Ftype = 2;
p = d;
}
void solve3() { // 双曲线
Ftype = 3;
a = d * k / (k * k - 1), c = k * a, b2 = c * c - a * a;
}

void run() {
failed = 0;
db p[2][3]; len = 0;
for (int i = 0; i <= 1; ++i) scanf("%lf%lf%lf", &p[i][0], &p[i][1], &p[i][2]);
for (int i = 0; i <= 2; ++i) len += (p[0][i] - p[1][i]) * (p[0][i] - p[1][i]);
len = sqrt(len);
scanf("%lf%lf%lf", &d, &l, &k);
l1 = l, l2 = len - l;
if (k < 1) solve1(); else if (k == 1) solve2(); else if (k > 1) solve3();
if (!failed) printf("%.8lf\n", calculate() / 2);
else puts("-1");
}
int main() {
int t;
scanf("%d", &t);
file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 6/7
2021/12/2 下午1:24 厦门大学2021年铃盛杯C语言积分赛第二周周赛题解

while (t--) {
run();
}
return 0;
}

**赛后评价:**这道题本来是我按照周赛E的难度出的题目,但就在周赛二前一天晚上,李泽政学长找到
我,对我说:“出题组已经研究决定了,就用你这道题来做周赛二的压轴题。”我当时就说:“我这道题明明
是按照周赛E题难度出的题目,怎么就拿来当周赛的压轴题了,我也实在不是谦虚,还是另请高明吧。”

本题最后只有一个人通过还是非常意外的,不知道选手们是不是受了前面题目的影响。

file:///C:/Users/ZezhengLi/Documents/周赛二3-6题题解.html 7/7

You might also like