蓝桥杯15届,研究生组个人题解

试题A: 劲舞团 本题总分:5分 【问题描述】 小蓝最近迷上了一款名为“劲舞团”的游戏,具体来说,只要按照游戏中 给出的键位提示依次按出对应的键位,游戏人物便可以跟随节奏跳舞。对于连 续的K次正确敲击,如果任意连续的两次敲击间间隔时间都小于等于1s,那么 我们称这是一次K连击。现在给出一局小蓝的游戏记录文件,log.txt中记录了 N 条记录,每条记录有三个字段,依次为正确的敲击字符、小蓝打出的字符、 打出字符的时间对应的毫秒时间戳。现在请你计算下最长的K连击是多少,你 只需要输出K的值。

【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分

排序遍历统计即可,答案为9

试题B: 召唤数学精灵 本题总分:5分 【问题描述】 数学家们发现了两种用于召唤强大的数学精灵的仪式,这两种仪式分别被 称为累加法仪式A(n)和累乘法仪式B(n)。 累加法仪式 A(n) 是将从 1 到 n 的所有数字进行累加求和,即:A(n) = 1 +2+···+n 。 累乘法仪式B(n) 则是将从 1 到n的所有数字进行累乘求积,即:B(n)= 1 ×2×···×n 。 据说,当某个数字i满足A(i)−B(i) 能被 100 整除时,数学精灵就会被召 唤出来。 现在,请你寻找在1到2024041331404202 之间有多少个数字 i,能够成功 召唤出强大的数学精灵。

【答案提交】 这是一道结果填空题,你只需要算出结果后提交即可。本题的结果为一个 整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

打印找规律,4202结尾为85个,202404133140这一段每一个数字有20个,所以答案就是202404133140*20+85

试题C: 封闭图形个数 时间限制: 1.0s 内存限制: 256.0MB 本题总分:10分 【问题描述】 在蓝桥王国,数字的大小不仅仅取决于它们的数值大小,还取决于它们所 形成的“封闭图形”的个数。 封闭图形是指数字中完全封闭的空间,例如数字1、2、3、5、7都没有形 成封闭图形,而数字0、4、6、9分别形成了1个封闭图形,数字8则形成了2 个封闭图形。值得注意的是,封闭图形的个数是可以累加的。例如,对于数字 68,由于 6 形成了1个封闭图形,而8形成了2个,所以68形成的封闭图形 的个数总共为3。 在比较两个数的大小时,如果它们的封闭图形个数不同,那么封闭图形个 数较多的数更大。例如,数字41和数字18,它们对应的封闭图形的个数分别 为1和2,因此数字41小于数组18。如果两个数的封闭图形个数相同,那么 数值较大的数更大。例如,数字14和数字41,它们的封闭图形的个数都是1, 但14<41,所以数字14 小于数字41。如果两个数字的封闭图形个数和数值都 相同,那么这两个数字被认为是相等的。 小蓝对蓝桥王国的数字大小规则十分感兴趣。现在,他将给定你n个数 a1, a2, . . . , an,请你按照蓝桥王国的数字大小规则,将这 n 数从小到大排序,并 输出排序后结果。

【输入格式】 输入的第一行包含一个整数n,表示给定的数字个数。 第二行包含n个整数a1,a2,...,an ,相邻整数之间使用一个空格分隔,表 示待排序的数字。

【输出格式】 输出一行包含n个整数,相邻整数之间使用一个空格分隔,表示按照蓝桥 王国的数字大小规则从小到大排序后的结果

这个简单,大概是统计数位的权值,然后map嵌套set再打印就行了

试题D: 吊坠 时间限制: 1.0s 内存限制: 256.0MB 本题总分:10分 【问题描述】 小蓝想制作一个吊坠,他手上有n个长度为m的首尾相连的环形字符串 {s1, s2, · · · , sn} ,他想用 n − 1 条边将这 n 个字符串连接起来做成吊坠,要求所 有的字符串连完后形成一个整体。连接两个字符串si,sj 的边的边权为这两个字 符串的最长公共子串的长度(可以按环形旋转改变起始位置,但不能翻转),小 蓝希望连完后的这n−1条边的边权和最大,这样的吊坠他觉得最好看,请计算 最大的边权和是多少。

【输入格式】 输入的第一行包含两个正整数n,m,用一个空格分隔。 接下来n行,每行包含一个长度为m的字符串,分别表示s1,s2,··· ,sn 。

【输出格式】 输出一行包含一个整数表示答案

先计算权值,将每个s做成s+s的形式,然后先计算s1每一段的哈希值,用map存储哈希值和长度,再算s2的哈希值去匹配找到最大长度,因为循环的原因,起点l位于0到m,终点r再l到l+m以内

试题E: 挖矿 时间限制: 1.0s 内存限制: 256.0MB 本题总分:15分 【问题描述】 小蓝正在数轴上挖矿,数轴上一共有n个矿洞,第i个矿洞的坐标为ai。 小蓝从0出发,每次可以向左或向右移动1的距离,当路过一个矿洞时,就会 进行挖矿作业,获得1单位矿石,但一个矿洞不能被多次挖掘。小蓝想知道在 移动距离不超过m的前提下,最多能获得多少单位矿石?

【输入格式】 输入的第一行包含两个正整数n,m,用一个空格分隔。 第二行包含n个整数a1,a2,··· ,an ,相邻整数之间使用一个空格分隔。

【输出格式】 输出一行包含一个整数表示答案

先把数据整体右移1e6+1 再计算前缀和,根据m的奇偶性枚举单程路段的长度i,那么区间就是pre[st+1]-pre[st-(m-i)/2-1],左右都要枚举一次

试题F: 智力测试 时间限制: 1.0s 内存限制: 256.0MB 本题总分:15分 【问题描述】 小蓝考上了世界上最好的魔法师学校,然而入学第一件事就是智力测试, 老师给出了一个n×m大小的棋盘,同时对每行每列设置了权重{R1,R2,··· ,Rn} 和{C1,C2,··· ,Cm} ,因此,对于第 r 行第 c 列的格子 (r,c) ,其权重为一个二 元组(Rr,Cc) 。 小蓝可以在格子之间进行移动,若某时刻小蓝在格子(r,c),那么他可以一 步走到任意的格子(r′,c) 或 (r,c′) ,其中 r′,c′ 满足: (1)Rr′ > Rr,Cc′ > Cc , (2)r′′.Rr′ > Rr′′ > Rr; c′′.Cc′ > Cc′′ > Cr 。 之后,老师提出了T 个问题,第i个问题为:假设小蓝从格子(si r,si c) 出 发,移动到格子(ti r,ti c) 有多少种不同的走法,答案对 1000000007 取模。

【输入格式】 输入的第一行包含三个正整数n,m,T ,相邻整数之间使用一个空格分隔。 第二行包含n个正整数R1,R2,··· ,Rn ,相邻整数之间使用一个空格分隔。 第三行包含m个正整数C1,C2,··· ,Cm ,相邻整数之间使用一个空格分隔。 接下来T 行,第i行包含四个正整数si r,si c,ti r,ti c ,相邻整数之间使用一个 空格分隔。

【输出格式】 输出T 行,每行包含一个整数,依次表示每个问题的答案

没时间做

试题G: 最大异或结点 时间限制: 1.0s 内存限制: 256.0MB 本题总分:20分 【问题描述】 小蓝有一棵树,树中包含N 个结点,编号为0,1,2,··· ,N−1 ,其中每个 结点上都有一个整数Xi 。他可以从树中任意选择两个不直接相连的结点a、b 并获得分数Xa⊕Xb ,其中⊕表示按位异或操作。 请问小蓝可以获得的最大分数是多少?

【输入格式】 输入的第一行包含一个整数N,表示有N个结点。 第二行包含N个整数X1,X2,··· ,XN ,相邻整数之间使用一个空格分隔。 第三行包含N 个整数F1,F2,··· ,FN ,相邻整数之间使用一个空格分隔, 其中第i个整数表示i的父结点编号,Fi=−1表示结点i没有父结点。

【输出格式】 输出一行包含一个整数表示答案

先把全部数据建立字典树,然后dfs每次先删除父亲和儿子值的部分,然后跑一遍字典树得到答案取最大值,计算之后要把父亲和儿子的值加回去字典树

试题H: 植物生命力 时间限制: 1.0s 内存限制: 256.0MB 本题总分:20分 【问题描述】 小蓝是一位资深的植物学家,他专注于研究植物的相互关系和生命力。在 他所照料的森林中,每个品种的植物都拥有独特的生命力,彼此之间互不相同。 植物的生命力会影响其下级品种的生长。具体地,如果下级品种的生命力 数值无法被上级品种的生命力数值整除,或者下级品种的生命力数值大于上级 品种的生命力数值时,它们便会受到压制,无法茁壮成长。 为了深入研究和定量分析这一现象,小蓝构建了一种模型。他将森林中的 植物品种关系抽象成了一棵包含n个结点的树,结点的编号从1到n,代表不 同的植物品种。其中,树的根结点编号为s,结点i(1≤i≤n)的生命力表示 为ai。 现在,小蓝想要对于每个结点i,统计其子树(以i为根的子树)中同时满 足以下两个条件的子结点的数量: 1. 子结点的生命力小于结点i的生命力ai。 2. 子结点的生命力无法被结点i的生命力ai 整除。 请你帮助小蓝计算出所有子树中满足条件的结点个数的总和。

【输入格式】 输入的第一行包含两个整数n和s,分别表示结点的数量和根结点的编号。 第二行包含n个互不相同的整数a1,a2,··· ,an,相邻整数之间使用一个空 格分隔,其中ai 表示编号为i的结点的生命力。 接下来的n−1行,每行包含两个整数u和v,用一个空格分隔,表示编 号为u和v的结点之间存在一条边。

【输出格式】 输出一行包含一个整数,表示所有子树中满足条件的结点个数的总和

做个动态开点的线段树,dfs遍历树,每到一个节点就新建一个线段树的节点,然后把它的值的位置加1,再跑子节点,每次把子节点的线段树的节点和当前树的节点合并起来,就能拿到子节点的数值情况;

接下来对当前节点做质因数分解,然后跑一边dfs得到因数的值,排个序,那么答案就是每两个因数的中间那一段的求和,每次用线段树查那段区间的数有多少个

这里给出我自己的代码,因为没给出ai的值的范围,所以默认取long long,要是数字很大(1e18)那么大那质因数分解有问题,该用帕拉德ρ来分解吧

int ans = 0;
set<int>k;
long long val[100001];
vector<int>e[100001];
long long L = 1e18 + 7, R = 0;
struct node {
    int sum;
    node* l, * r;
};
void add(node*& x, long long L, long long R, long long l, long long r) {
    if (!x) x = new node();
    if (l <= L && R <= r) {
        x->sum = 1;
        return;
    }
    long long mid = (L + R) >> 1;
    if (l <= mid) add(x->l, L, mid, l, r);
    if (r > mid) add(x->r, mid + 1, R, l, r);
    x->sum = (x->l ? x->l->sum : 0) + (x->r ? x->r->sum : 0);
}

int query(node* x, long long L, long long R, long long l, long long r) {
    if (!x || l > R || r < L) return 0;
    if (l <= L && R <= r) return x->sum;
    long long mid = (L + R) >> 1;
    return query(x->l, L, mid, l, r) + query(x->r, mid + 1, R, l, r);
}

void merge(node*& x, node* b) {
    if (!b) return;
    if (!x && b) {
        x = b;
        return;
    }
    if (!x && !b) return;
    if (x && b) merge(x->l, b->l), merge(x->r, b->r);
    x->sum = (x->l ? x->l->sum : 0) + (x->r ? x->r->sum : 0);
}

map<long long, int>p;
void z1(long long val, long long pre) {
    auto it = p.upper_bound(pre);
    if (it == p.end()) {
        k.insert(val);
        return;
    }
    long long temp = 1;
    for (int i = 0; i <= it->second; i++) {
        z1(val * temp, it->first);
        temp *= it->first;
    }
}
vector<long long> z(long long a) {
    p.clear();
    for (long long i = 2; i * i <= a; i++) {
        while (a % i == 0) {
            p[i]++;
            a /= i;
        }
    }
    if (a > 1) p[a]++;
    k.clear();
    z1(1, 1);
    vector<long long>res = { k.begin(),k.end() };
    return res;
}
int cal(node* x, long long a) {
    int res = 0;
    vector<long long>len = z(a);
    for (int i = 1; i < len.size(); i++) {
        res += query(x, L, R, len[i - 1] + 1, len[i] - 1);
    }
    return res;
}
node* fun(int x, int pre) {
    node* t_x = new node();
    add(t_x, L, R, val[x], val[x]);
    for (int i = 0; i < e[x].size(); i++) {
        if (e[x][i] == pre) continue;
        node* ne_t = fun(e[x][i], x);
        merge(t_x, ne_t);
    }
    ans += cal(t_x, val[x]);
    return t_x;
}
int main() {
    int n, s;
    cin >> n >> s;
    for (int i = 1; i <= n; i++) {
        cin >> val[i];
        L = min(val[i], L);
        R = max(val[i], R);
    }
    for (int i = 1; i < n; i++) {
        int a, b; cin >> a >> b;
        e[a].push_back(b);
        e[b].push_back(a);
    }
    fun(s, 0);
    cout << ans;
    return 0;
}

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值